Index: ios/chrome/browser/ui/collection_view/collection_view_model_unittest.mm |
diff --git a/ios/chrome/browser/ui/collection_view/collection_view_model_unittest.mm b/ios/chrome/browser/ui/collection_view/collection_view_model_unittest.mm |
new file mode 100644 |
index 0000000000000000000000000000000000000000..922bdd37a33512dc88ce0fdc7f8b7a0ce69d8370 |
--- /dev/null |
+++ b/ios/chrome/browser/ui/collection_view/collection_view_model_unittest.mm |
@@ -0,0 +1,591 @@ |
+// Copyright 2016 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#import "ios/chrome/browser/ui/collection_view/collection_view_model.h" |
+ |
+#include "base/mac/foundation_util.h" |
+#include "base/mac/scoped_nsobject.h" |
+#import "ios/chrome/browser/ui/collection_view/cells/collection_view_item.h" |
+#include "testing/gtest/include/gtest/gtest.h" |
+#include "testing/gtest_mac.h" |
+ |
+@interface CollectionViewModel (Testing) |
+// Adds an item with the given type to the section with the given identifier. |
+// It is possible to add multiple items with the same type to the same section. |
+// Sharing types across sections is undefined behavior. |
+- (void)addItemWithType:(NSInteger)itemType |
+ toSectionWithIdentifier:(NSInteger)sectionIdentifier; |
+@end |
+ |
+@implementation CollectionViewModel (Testing) |
+ |
+- (void)addItemWithType:(NSInteger)itemType |
+ toSectionWithIdentifier:(NSInteger)sectionIdentifier { |
+ base::scoped_nsobject<CollectionViewItem> item( |
+ [[CollectionViewItem alloc] initWithType:itemType]); |
+ [self addItem:item toSectionWithIdentifier:sectionIdentifier]; |
+} |
+ |
+@end |
+ |
+namespace { |
+ |
+typedef NS_ENUM(NSInteger, SectionIdentifier) { |
+ SectionIdentifierCheese = kSectionIdentifierEnumZero, |
+ SectionIdentifierWeasley, |
+}; |
+ |
+typedef NS_ENUM(NSInteger, ItemType) { |
+ ItemTypeCheeseHeader = kItemTypeEnumZero, |
+ ItemTypeCheeseCheddar, |
+ ItemTypeCheeseGouda, |
+ ItemTypeCheesePepperJack, |
+ ItemTypeWeasleyRon, |
+ ItemTypeWeasleyGinny, |
+ ItemTypeWeasleyArthur, |
+ ItemTypeWeasleyFooter, |
+}; |
+ |
+void LogSink(const std::string& str) { |
+ // No-op. |
+} |
+ |
+TEST(CollectionViewModelTest, EmptyModel) { |
+ base::scoped_nsobject<CollectionViewModel> model( |
+ [[CollectionViewModel alloc] init]); |
+ |
+ // Check there are no items. |
+ EXPECT_EQ(NO, [model hasItemAtIndexPath:[NSIndexPath indexPathForItem:0 |
+ inSection:0]]); |
+ |
+ // Check the collection view data sourcing methods. |
+ EXPECT_EQ(0, [model numberOfSections]); |
+} |
+ |
+TEST(CollectionViewModelTest, SingleSection) { |
+ base::scoped_nsobject<CollectionViewModel> model( |
+ [[CollectionViewModel alloc] init]); |
+ |
+ [model addSectionWithIdentifier:SectionIdentifierCheese]; |
+ [model addItemWithType:ItemTypeCheeseCheddar |
+ toSectionWithIdentifier:SectionIdentifierCheese]; |
+ [model addItemWithType:ItemTypeCheeseGouda |
+ toSectionWithIdentifier:SectionIdentifierCheese]; |
+ [model addItemWithType:ItemTypeCheesePepperJack |
+ toSectionWithIdentifier:SectionIdentifierCheese]; |
+ |
+ // Check there are some items but not more. |
+ EXPECT_EQ(YES, [model hasItemAtIndexPath:[NSIndexPath indexPathForItem:0 |
+ inSection:0]]); |
+ EXPECT_EQ(YES, [model hasItemAtIndexPath:[NSIndexPath indexPathForItem:2 |
+ inSection:0]]); |
+ EXPECT_EQ(NO, [model hasItemAtIndexPath:[NSIndexPath indexPathForItem:3 |
+ inSection:0]]); |
+ EXPECT_EQ(NO, [model hasItemAtIndexPath:[NSIndexPath indexPathForItem:0 |
+ inSection:1]]); |
+ |
+ // Check the collection view data sourcing methods. |
+ EXPECT_EQ(1, [model numberOfSections]); |
+ EXPECT_EQ(3, [model numberOfItemsInSection:0]); |
+ |
+ // Check the section identifier <-> section correspondance methods. |
+ EXPECT_EQ(SectionIdentifierCheese, [model sectionIdentifierForSection:0]); |
+ EXPECT_EQ(0, [model sectionForSectionIdentifier:SectionIdentifierCheese]); |
+ |
+ // Check the item type <-> item correspondance methods. |
+ EXPECT_EQ(ItemTypeCheeseCheddar, |
+ [model itemTypeForIndexPath:[NSIndexPath indexPathForItem:0 |
+ inSection:0]]); |
+ EXPECT_EQ(ItemTypeCheeseGouda, |
+ [model itemTypeForIndexPath:[NSIndexPath indexPathForItem:1 |
+ inSection:0]]); |
+ EXPECT_EQ(ItemTypeCheesePepperJack, |
+ [model itemTypeForIndexPath:[NSIndexPath indexPathForItem:2 |
+ inSection:0]]); |
+} |
+ |
+TEST(CollectionViewModelTest, SingleSectionWithMissingItems) { |
+ base::scoped_nsobject<CollectionViewModel> model( |
+ [[CollectionViewModel alloc] init]); |
+ |
+ [model addSectionWithIdentifier:SectionIdentifierCheese]; |
+ [model addItemWithType:ItemTypeCheeseCheddar |
+ toSectionWithIdentifier:SectionIdentifierCheese]; |
+ // "Gouda" is intentionally omitted. |
+ [model addItemWithType:ItemTypeCheesePepperJack |
+ toSectionWithIdentifier:SectionIdentifierCheese]; |
+ |
+ // Check the item type <-> item correspondance methods. |
+ EXPECT_EQ(ItemTypeCheeseCheddar, |
+ [model itemTypeForIndexPath:[NSIndexPath indexPathForItem:0 |
+ inSection:0]]); |
+ EXPECT_EQ(ItemTypeCheesePepperJack, |
+ [model itemTypeForIndexPath:[NSIndexPath indexPathForItem:1 |
+ inSection:0]]); |
+} |
+ |
+TEST(CollectionViewModelTest, MultipleSections) { |
+ base::scoped_nsobject<CollectionViewModel> model( |
+ [[CollectionViewModel alloc] init]); |
+ |
+ [model addSectionWithIdentifier:SectionIdentifierCheese]; |
+ // "Cheddar" and "Gouda" are intentionally omitted. |
+ [model addItemWithType:ItemTypeCheesePepperJack |
+ toSectionWithIdentifier:SectionIdentifierCheese]; |
+ |
+ [model addSectionWithIdentifier:SectionIdentifierWeasley]; |
+ // "Ron" is intentionally omitted. |
+ [model addItemWithType:ItemTypeWeasleyGinny |
+ toSectionWithIdentifier:SectionIdentifierWeasley]; |
+ [model addItemWithType:ItemTypeWeasleyArthur |
+ toSectionWithIdentifier:SectionIdentifierWeasley]; |
+ |
+ // Check the collection view data sourcing methods. |
+ EXPECT_EQ(2, [model numberOfSections]); |
+ EXPECT_EQ(2, [model numberOfItemsInSection:1]); |
+ |
+ // Check the section identifier <-> section correspondance methods. |
+ EXPECT_EQ(SectionIdentifierCheese, [model sectionIdentifierForSection:0]); |
+ EXPECT_EQ(0, [model sectionForSectionIdentifier:SectionIdentifierCheese]); |
+ EXPECT_EQ(SectionIdentifierWeasley, [model sectionIdentifierForSection:1]); |
+ EXPECT_EQ(1, [model sectionForSectionIdentifier:SectionIdentifierWeasley]); |
+ |
+ // Check the item type <-> item correspondance methods. |
+ EXPECT_EQ(ItemTypeCheesePepperJack, |
+ [model itemTypeForIndexPath:[NSIndexPath indexPathForItem:0 |
+ inSection:0]]); |
+ EXPECT_EQ(ItemTypeWeasleyGinny, |
+ [model itemTypeForIndexPath:[NSIndexPath indexPathForItem:0 |
+ inSection:1]]); |
+ EXPECT_EQ(ItemTypeWeasleyArthur, |
+ [model itemTypeForIndexPath:[NSIndexPath indexPathForItem:1 |
+ inSection:1]]); |
+} |
+ |
+TEST(CollectionViewModelTest, GetIndexPathFromModelCoordinates) { |
+ base::scoped_nsobject<CollectionViewModel> model( |
+ [[CollectionViewModel alloc] init]); |
+ |
+ [model addSectionWithIdentifier:SectionIdentifierCheese]; |
+ [model addItemWithType:ItemTypeCheesePepperJack |
+ toSectionWithIdentifier:SectionIdentifierCheese]; |
+ [model addSectionWithIdentifier:SectionIdentifierWeasley]; |
+ [model addItemWithType:ItemTypeWeasleyGinny |
+ toSectionWithIdentifier:SectionIdentifierWeasley]; |
+ [model addItemWithType:ItemTypeWeasleyArthur |
+ toSectionWithIdentifier:SectionIdentifierWeasley]; |
+ |
+ // Check the index path retrieval method for a single item. |
+ NSIndexPath* indexPath = |
+ [model indexPathForItemType:ItemTypeWeasleyGinny |
+ sectionIdentifier:SectionIdentifierWeasley]; |
+ EXPECT_EQ(1, indexPath.section); |
+ EXPECT_EQ(0, indexPath.item); |
+ |
+ // Check the index path retrieval method for the first item. |
+ indexPath = [model indexPathForItemType:ItemTypeWeasleyGinny |
+ sectionIdentifier:SectionIdentifierWeasley |
+ atIndex:0]; |
+ EXPECT_EQ(1, indexPath.section); |
+ EXPECT_EQ(0, indexPath.item); |
+} |
+ |
+TEST(CollectionViewItemTest, RepeatedItems) { |
+ base::scoped_nsobject<CollectionViewModel> model( |
+ [[CollectionViewModel alloc] init]); |
+ |
+ [model addSectionWithIdentifier:SectionIdentifierCheese]; |
+ [model addItemWithType:ItemTypeCheesePepperJack |
+ toSectionWithIdentifier:SectionIdentifierCheese]; |
+ [model addSectionWithIdentifier:SectionIdentifierWeasley]; |
+ [model addItemWithType:ItemTypeWeasleyGinny |
+ toSectionWithIdentifier:SectionIdentifierWeasley]; |
+ [model addItemWithType:ItemTypeWeasleyArthur |
+ toSectionWithIdentifier:SectionIdentifierWeasley]; |
+ [model addItemWithType:ItemTypeWeasleyArthur |
+ toSectionWithIdentifier:SectionIdentifierWeasley]; |
+ [model addItemWithType:ItemTypeWeasleyArthur |
+ toSectionWithIdentifier:SectionIdentifierWeasley]; |
+ |
+ NSIndexPath* indexPath = |
+ [model indexPathForItemType:ItemTypeWeasleyArthur |
+ sectionIdentifier:SectionIdentifierWeasley]; |
+ |
+ // Check the index path retrieval method for a single item on a repeated item. |
+ EXPECT_EQ(1, indexPath.section); |
+ EXPECT_EQ(1, indexPath.item); |
+ |
+ // Check the index path retrieval method for a repeated item. |
+ indexPath = [model indexPathForItemType:ItemTypeWeasleyArthur |
+ sectionIdentifier:SectionIdentifierWeasley |
+ atIndex:1]; |
+ |
+ EXPECT_EQ(1, indexPath.section); |
+ EXPECT_EQ(2, indexPath.item); |
+} |
+ |
+TEST(CollectionViewModelTest, RepeatedItemIndex) { |
+ base::scoped_nsobject<CollectionViewModel> model( |
+ [[CollectionViewModel alloc] init]); |
+ |
+ [model addSectionWithIdentifier:SectionIdentifierCheese]; |
+ [model addItemWithType:ItemTypeCheesePepperJack |
+ toSectionWithIdentifier:SectionIdentifierCheese]; |
+ [model addSectionWithIdentifier:SectionIdentifierWeasley]; |
+ [model addItemWithType:ItemTypeWeasleyGinny |
+ toSectionWithIdentifier:SectionIdentifierWeasley]; |
+ [model addItemWithType:ItemTypeWeasleyArthur |
+ toSectionWithIdentifier:SectionIdentifierWeasley]; |
+ [model addItemWithType:ItemTypeWeasleyArthur |
+ toSectionWithIdentifier:SectionIdentifierWeasley]; |
+ [model addItemWithType:ItemTypeWeasleyArthur |
+ toSectionWithIdentifier:SectionIdentifierWeasley]; |
+ [model addItemWithType:ItemTypeWeasleyGinny |
+ toSectionWithIdentifier:SectionIdentifierWeasley]; |
+ [model addItemWithType:ItemTypeWeasleyArthur |
+ toSectionWithIdentifier:SectionIdentifierWeasley]; |
+ |
+ // Check the index path <-> index in item type correspondance method. |
+ EXPECT_EQ( |
+ 0U, [model indexInItemTypeForIndexPath:[NSIndexPath indexPathForItem:0 |
+ inSection:0]]); |
+ EXPECT_EQ( |
+ 0U, [model indexInItemTypeForIndexPath:[NSIndexPath indexPathForItem:1 |
+ inSection:1]]); |
+ EXPECT_EQ( |
+ 2U, [model indexInItemTypeForIndexPath:[NSIndexPath indexPathForItem:3 |
+ inSection:1]]); |
+ EXPECT_EQ( |
+ 3U, [model indexInItemTypeForIndexPath:[NSIndexPath indexPathForItem:5 |
+ inSection:1]]); |
+} |
+ |
+TEST(CollectionViewModelTest, RetrieveAddedItem) { |
+ base::scoped_nsobject<CollectionViewModel> model( |
+ [[CollectionViewModel alloc] init]); |
+ |
+ [model addSectionWithIdentifier:SectionIdentifierCheese]; |
+ base::scoped_nsobject<CollectionViewItem> someItem( |
+ [[CollectionViewItem alloc] initWithType:ItemTypeCheeseGouda]); |
+ [model addItem:someItem toSectionWithIdentifier:SectionIdentifierCheese]; |
+ |
+ // Check that the item is the same in the model. |
+ EXPECT_EQ(someItem, [model itemAtIndexPath:[NSIndexPath indexPathForItem:0 |
+ inSection:0]]); |
+} |
+ |
+TEST(CollectionViewModelTest, RetrieveItemsInSection) { |
+ base::scoped_nsobject<CollectionViewModel> model( |
+ [[CollectionViewModel alloc] init]); |
+ [model addSectionWithIdentifier:SectionIdentifierCheese]; |
+ base::scoped_nsobject<CollectionViewItem> cheddar( |
+ [[CollectionViewItem alloc] initWithType:ItemTypeCheeseCheddar]); |
+ [model addItem:cheddar toSectionWithIdentifier:SectionIdentifierCheese]; |
+ base::scoped_nsobject<CollectionViewItem> pepperJack( |
+ [[CollectionViewItem alloc] initWithType:ItemTypeCheesePepperJack]); |
+ [model addItem:pepperJack toSectionWithIdentifier:SectionIdentifierCheese]; |
+ base::scoped_nsobject<CollectionViewItem> gouda( |
+ [[CollectionViewItem alloc] initWithType:ItemTypeCheeseGouda]); |
+ [model addItem:gouda toSectionWithIdentifier:SectionIdentifierCheese]; |
+ |
+ NSArray* cheeseItems = |
+ [model itemsInSectionWithIdentifier:SectionIdentifierCheese]; |
+ EXPECT_EQ(3U, [cheeseItems count]); |
+ EXPECT_NSEQ(cheddar, cheeseItems[0]); |
+ EXPECT_NSEQ(pepperJack, cheeseItems[1]); |
+ EXPECT_NSEQ(gouda, cheeseItems[2]); |
+} |
+ |
+TEST(CollectionViewModelTest, InvalidIndexPath) { |
+ base::scoped_nsobject<CollectionViewModel> model( |
+ [[CollectionViewModel alloc] init]); |
+ [model addSectionWithIdentifier:SectionIdentifierCheese]; |
+ |
+ bool out_of_bounds_exception_thrown = false; |
+ @try { |
+ logging::SetLogAssertHandler(&LogSink); |
+ [model indexInItemTypeForIndexPath:[NSIndexPath indexPathForItem:0 |
+ inSection:0]]; |
+ } @catch (NSException* exception) { |
+ if ([[exception name] isEqualToString:NSRangeException]) { |
+ out_of_bounds_exception_thrown = true; |
+ } |
+ } |
+ EXPECT_TRUE(out_of_bounds_exception_thrown); |
+} |
+ |
+TEST(CollectionViewModelTest, RemoveItems) { |
+ base::scoped_nsobject<CollectionViewModel> model( |
+ [[CollectionViewModel alloc] init]); |
+ |
+ [model addSectionWithIdentifier:SectionIdentifierCheese]; |
+ [model addItemWithType:ItemTypeCheesePepperJack |
+ toSectionWithIdentifier:SectionIdentifierCheese]; |
+ [model addItemWithType:ItemTypeCheeseGouda |
+ toSectionWithIdentifier:SectionIdentifierCheese]; |
+ |
+ [model addSectionWithIdentifier:SectionIdentifierWeasley]; |
+ [model addItemWithType:ItemTypeWeasleyGinny |
+ toSectionWithIdentifier:SectionIdentifierWeasley]; |
+ [model addItemWithType:ItemTypeWeasleyArthur |
+ toSectionWithIdentifier:SectionIdentifierWeasley]; |
+ [model addItemWithType:ItemTypeWeasleyArthur |
+ toSectionWithIdentifier:SectionIdentifierWeasley]; |
+ [model addItemWithType:ItemTypeWeasleyArthur |
+ toSectionWithIdentifier:SectionIdentifierWeasley]; |
+ [model addItemWithType:ItemTypeWeasleyRon |
+ toSectionWithIdentifier:SectionIdentifierWeasley]; |
+ |
+ [model removeItemWithType:ItemTypeCheesePepperJack |
+ fromSectionWithIdentifier:SectionIdentifierCheese]; |
+ [model removeItemWithType:ItemTypeWeasleyGinny |
+ fromSectionWithIdentifier:SectionIdentifierWeasley]; |
+ [model removeItemWithType:ItemTypeWeasleyArthur |
+ fromSectionWithIdentifier:SectionIdentifierWeasley |
+ atIndex:2]; |
+ |
+ // Check the collection view data sourcing methods. |
+ EXPECT_EQ(2, [model numberOfSections]); |
+ |
+ // Check the index path retrieval method for a single item. |
+ NSIndexPath* indexPath = [model indexPathForItemType:ItemTypeCheeseGouda |
+ sectionIdentifier:SectionIdentifierCheese]; |
+ EXPECT_EQ(0, indexPath.section); |
+ EXPECT_EQ(0, indexPath.item); |
+ |
+ // Check the index path retrieval method for a repeated item. |
+ indexPath = [model indexPathForItemType:ItemTypeWeasleyArthur |
+ sectionIdentifier:SectionIdentifierWeasley |
+ atIndex:1]; |
+ EXPECT_EQ(1, indexPath.section); |
+ EXPECT_EQ(1, indexPath.item); |
+ |
+ // Check the index path retrieval method for a single item. |
+ indexPath = [model indexPathForItemType:ItemTypeWeasleyRon |
+ sectionIdentifier:SectionIdentifierWeasley]; |
+ EXPECT_EQ(1, indexPath.section); |
+ EXPECT_EQ(2, indexPath.item); |
+} |
+ |
+TEST(CollectionViewModelTest, RemoveSections) { |
+ base::scoped_nsobject<CollectionViewModel> model( |
+ [[CollectionViewModel alloc] init]); |
+ |
+ // Empty section. |
+ [model addSectionWithIdentifier:SectionIdentifierWeasley]; |
+ |
+ // Section with items. |
+ [model addSectionWithIdentifier:SectionIdentifierCheese]; |
+ [model addItemWithType:ItemTypeCheesePepperJack |
+ toSectionWithIdentifier:SectionIdentifierCheese]; |
+ [model addItemWithType:ItemTypeCheeseGouda |
+ toSectionWithIdentifier:SectionIdentifierCheese]; |
+ |
+ // Check the collection view data sourcing methods. |
+ EXPECT_EQ(2, [model numberOfSections]); |
+ EXPECT_EQ(0, [model numberOfItemsInSection:0]); |
+ EXPECT_EQ(2, [model numberOfItemsInSection:1]); |
+ |
+ // Remove an empty section. |
+ [model removeSectionWithIdentifier:SectionIdentifierWeasley]; |
+ |
+ // Check that the section was removed. |
+ EXPECT_EQ(1, [model numberOfSections]); |
+ EXPECT_EQ(2, [model numberOfItemsInSection:0]); |
+ |
+ // Remove a section with items. |
+ [model removeSectionWithIdentifier:SectionIdentifierCheese]; |
+ |
+ // Check that the section and its items were removed. |
+ EXPECT_EQ(0, [model numberOfSections]); |
+} |
+ |
+TEST(CollectionViewModelTest, QueryItemsFromModelCoordinates) { |
+ base::scoped_nsobject<CollectionViewModel> model( |
+ [[CollectionViewModel alloc] init]); |
+ |
+ EXPECT_FALSE([model hasSectionForSectionIdentifier:SectionIdentifierWeasley]); |
+ EXPECT_FALSE([model hasItemForItemType:ItemTypeCheeseCheddar |
+ sectionIdentifier:SectionIdentifierCheese]); |
+ EXPECT_FALSE([model hasItemForItemType:ItemTypeCheeseGouda |
+ sectionIdentifier:SectionIdentifierCheese |
+ atIndex:1]); |
+ |
+ // Section with items. |
+ [model addSectionWithIdentifier:SectionIdentifierCheese]; |
+ [model addItemWithType:ItemTypeCheesePepperJack |
+ toSectionWithIdentifier:SectionIdentifierCheese]; |
+ [model addItemWithType:ItemTypeCheeseGouda |
+ toSectionWithIdentifier:SectionIdentifierCheese]; |
+ [model addItemWithType:ItemTypeCheeseGouda |
+ toSectionWithIdentifier:SectionIdentifierCheese]; |
+ |
+ EXPECT_TRUE([model hasSectionForSectionIdentifier:SectionIdentifierCheese]); |
+ EXPECT_FALSE([model hasItemForItemType:ItemTypeCheeseCheddar |
+ sectionIdentifier:SectionIdentifierCheese]); |
+ EXPECT_TRUE([model hasItemForItemType:ItemTypeCheesePepperJack |
+ sectionIdentifier:SectionIdentifierCheese]); |
+ EXPECT_TRUE([model hasItemForItemType:ItemTypeCheeseGouda |
+ sectionIdentifier:SectionIdentifierCheese |
+ atIndex:1]); |
+} |
+ |
+// Tests that inserted sections are added at the correct index. |
+TEST(CollectionViewModelTest, InsertSections) { |
+ base::scoped_nsobject<CollectionViewModel> model( |
+ [[CollectionViewModel alloc] init]); |
+ |
+ [model addSectionWithIdentifier:SectionIdentifierWeasley]; |
+ EXPECT_EQ(1, [model numberOfSections]); |
+ EXPECT_EQ(0, [model sectionForSectionIdentifier:SectionIdentifierWeasley]); |
+ |
+ [model insertSectionWithIdentifier:SectionIdentifierCheese atIndex:0]; |
+ EXPECT_EQ(2, [model numberOfSections]); |
+ EXPECT_EQ(1, [model sectionForSectionIdentifier:SectionIdentifierWeasley]); |
+ EXPECT_EQ(0, [model sectionForSectionIdentifier:SectionIdentifierCheese]); |
+ |
+ [model removeSectionWithIdentifier:SectionIdentifierCheese]; |
+ [model insertSectionWithIdentifier:SectionIdentifierCheese atIndex:1]; |
+ EXPECT_EQ(2, [model numberOfSections]); |
+ EXPECT_EQ(0, [model sectionForSectionIdentifier:SectionIdentifierWeasley]); |
+ EXPECT_EQ(1, [model sectionForSectionIdentifier:SectionIdentifierCheese]); |
+} |
+ |
+// Tests that inserted items are added at the correct index. |
+TEST(CollectionViewModelTest, InsertItemAtIndex) { |
+ base::scoped_nsobject<CollectionViewModel> model( |
+ [[CollectionViewModel alloc] init]); |
+ |
+ [model addSectionWithIdentifier:SectionIdentifierCheese]; |
+ [model addItemWithType:ItemTypeCheesePepperJack |
+ toSectionWithIdentifier:SectionIdentifierCheese]; |
+ [model addItemWithType:ItemTypeCheeseGouda |
+ toSectionWithIdentifier:SectionIdentifierCheese]; |
+ base::scoped_nsobject<CollectionViewItem> cheddarItem( |
+ [[CollectionViewItem alloc] initWithType:ItemTypeCheeseCheddar]); |
+ [model insertItem:cheddarItem |
+ inSectionWithIdentifier:SectionIdentifierCheese |
+ atIndex:1]; |
+ |
+ EXPECT_EQ(1, [model numberOfSections]); |
+ |
+ NSIndexPath* pepperJackIndexPath = |
+ [model indexPathForItemType:ItemTypeCheesePepperJack |
+ sectionIdentifier:SectionIdentifierCheese]; |
+ EXPECT_EQ(0, pepperJackIndexPath.section); |
+ EXPECT_EQ(0, pepperJackIndexPath.item); |
+ |
+ NSIndexPath* cheddarIndexPath = |
+ [model indexPathForItemType:ItemTypeCheeseCheddar |
+ sectionIdentifier:SectionIdentifierCheese]; |
+ EXPECT_EQ(0, cheddarIndexPath.section); |
+ EXPECT_EQ(1, cheddarIndexPath.item); |
+ |
+ NSIndexPath* goudaIndexPath = |
+ [model indexPathForItemType:ItemTypeCheeseGouda |
+ sectionIdentifier:SectionIdentifierCheese]; |
+ EXPECT_EQ(0, goudaIndexPath.section); |
+ EXPECT_EQ(2, goudaIndexPath.item); |
+} |
+ |
+TEST(CollectionViewModelTest, IndexPathsForItems) { |
+ base::scoped_nsobject<CollectionViewModel> model( |
+ [[CollectionViewModel alloc] init]); |
+ |
+ [model addSectionWithIdentifier:SectionIdentifierWeasley]; |
+ [model addItemWithType:ItemTypeWeasleyGinny |
+ toSectionWithIdentifier:SectionIdentifierWeasley]; |
+ // Added at index 1. |
+ base::scoped_nsobject<CollectionViewItem> item1( |
+ [[CollectionViewItem alloc] initWithType:ItemTypeWeasleyRon]); |
+ [model addItem:item1 toSectionWithIdentifier:SectionIdentifierWeasley]; |
+ [model addItemWithType:ItemTypeWeasleyGinny |
+ toSectionWithIdentifier:SectionIdentifierWeasley]; |
+ [model addItemWithType:ItemTypeWeasleyArthur |
+ toSectionWithIdentifier:SectionIdentifierWeasley]; |
+ // Repeated item added at index 4. |
+ base::scoped_nsobject<CollectionViewItem> item4( |
+ [[CollectionViewItem alloc] initWithType:ItemTypeWeasleyArthur]); |
+ [model addItem:item4 toSectionWithIdentifier:SectionIdentifierWeasley]; |
+ [model addItemWithType:ItemTypeWeasleyArthur |
+ toSectionWithIdentifier:SectionIdentifierWeasley]; |
+ [model addItemWithType:ItemTypeWeasleyArthur |
+ toSectionWithIdentifier:SectionIdentifierWeasley]; |
+ |
+ NSIndexPath* indexPath1 = [model indexPathForItem:item1 |
+ inSectionWithIdentifier:SectionIdentifierWeasley]; |
+ EXPECT_EQ(0, indexPath1.section); |
+ EXPECT_EQ(1, indexPath1.item); |
+ |
+ NSIndexPath* indexPath4 = [model indexPathForItem:item4 |
+ inSectionWithIdentifier:SectionIdentifierWeasley]; |
+ EXPECT_EQ(0, indexPath4.section); |
+ EXPECT_EQ(4, indexPath4.item); |
+} |
+ |
+TEST(CollectionViewModelTest, Headers) { |
+ base::scoped_nsobject<CollectionViewModel> model( |
+ [[CollectionViewModel alloc] init]); |
+ |
+ [model addSectionWithIdentifier:SectionIdentifierCheese]; |
+ base::scoped_nsobject<CollectionViewItem> cheeseHeader( |
+ [[CollectionViewItem alloc] initWithType:ItemTypeCheeseHeader]); |
+ [model setHeader:cheeseHeader |
+ forSectionWithIdentifier:SectionIdentifierCheese]; |
+ [model addItemWithType:ItemTypeCheeseGouda |
+ toSectionWithIdentifier:SectionIdentifierCheese]; |
+ [model addItemWithType:ItemTypeCheeseCheddar |
+ toSectionWithIdentifier:SectionIdentifierCheese]; |
+ [model addSectionWithIdentifier:SectionIdentifierWeasley]; |
+ [model addItemWithType:ItemTypeWeasleyRon |
+ toSectionWithIdentifier:SectionIdentifierWeasley]; |
+ [model addItemWithType:ItemTypeWeasleyGinny |
+ toSectionWithIdentifier:SectionIdentifierWeasley]; |
+ |
+ NSInteger cheeseSection = |
+ [model sectionForSectionIdentifier:SectionIdentifierCheese]; |
+ NSInteger weasleySection = |
+ [model sectionForSectionIdentifier:SectionIdentifierWeasley]; |
+ |
+ EXPECT_EQ(cheeseHeader.get(), |
+ [model headerForSectionWithIdentifier:SectionIdentifierCheese]); |
+ EXPECT_EQ(cheeseHeader.get(), [model headerForSection:cheeseSection]); |
+ |
+ EXPECT_FALSE([model headerForSectionWithIdentifier:SectionIdentifierWeasley]); |
+ EXPECT_FALSE([model headerForSection:weasleySection]); |
+} |
+ |
+TEST(CollectionViewModelTest, Footers) { |
+ base::scoped_nsobject<CollectionViewModel> model( |
+ [[CollectionViewModel alloc] init]); |
+ |
+ [model addSectionWithIdentifier:SectionIdentifierCheese]; |
+ [model addItemWithType:ItemTypeCheeseGouda |
+ toSectionWithIdentifier:SectionIdentifierCheese]; |
+ [model addItemWithType:ItemTypeCheeseCheddar |
+ toSectionWithIdentifier:SectionIdentifierCheese]; |
+ [model addSectionWithIdentifier:SectionIdentifierWeasley]; |
+ [model addItemWithType:ItemTypeWeasleyRon |
+ toSectionWithIdentifier:SectionIdentifierWeasley]; |
+ [model addItemWithType:ItemTypeWeasleyGinny |
+ toSectionWithIdentifier:SectionIdentifierWeasley]; |
+ base::scoped_nsobject<CollectionViewItem> weasleyFooter( |
+ [[CollectionViewItem alloc] initWithType:ItemTypeWeasleyFooter]); |
+ [model setFooter:weasleyFooter |
+ forSectionWithIdentifier:SectionIdentifierWeasley]; |
+ |
+ NSInteger cheeseSection = |
+ [model sectionForSectionIdentifier:SectionIdentifierCheese]; |
+ NSInteger weasleySection = |
+ [model sectionForSectionIdentifier:SectionIdentifierWeasley]; |
+ |
+ EXPECT_FALSE([model footerForSectionWithIdentifier:SectionIdentifierCheese]); |
+ EXPECT_FALSE([model footerForSection:cheeseSection]); |
+ |
+ EXPECT_EQ(weasleyFooter.get(), |
+ [model footerForSectionWithIdentifier:SectionIdentifierWeasley]); |
+ EXPECT_EQ(weasleyFooter.get(), [model footerForSection:weasleySection]); |
+} |
+ |
+} // namespace |