OLD | NEW |
(Empty) | |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #import "ios/chrome/browser/ui/collection_view/collection_view_model.h" |
| 6 |
| 7 #include "base/mac/foundation_util.h" |
| 8 #include "base/mac/scoped_nsobject.h" |
| 9 #import "ios/chrome/browser/ui/collection_view/cells/collection_view_item.h" |
| 10 #include "testing/gtest/include/gtest/gtest.h" |
| 11 #include "testing/gtest_mac.h" |
| 12 |
| 13 @interface CollectionViewModel (Testing) |
| 14 // Adds an item with the given type to the section with the given identifier. |
| 15 // It is possible to add multiple items with the same type to the same section. |
| 16 // Sharing types across sections is undefined behavior. |
| 17 - (void)addItemWithType:(NSInteger)itemType |
| 18 toSectionWithIdentifier:(NSInteger)sectionIdentifier; |
| 19 @end |
| 20 |
| 21 @implementation CollectionViewModel (Testing) |
| 22 |
| 23 - (void)addItemWithType:(NSInteger)itemType |
| 24 toSectionWithIdentifier:(NSInteger)sectionIdentifier { |
| 25 base::scoped_nsobject<CollectionViewItem> item( |
| 26 [[CollectionViewItem alloc] initWithType:itemType]); |
| 27 [self addItem:item toSectionWithIdentifier:sectionIdentifier]; |
| 28 } |
| 29 |
| 30 @end |
| 31 |
| 32 namespace { |
| 33 |
| 34 typedef NS_ENUM(NSInteger, SectionIdentifier) { |
| 35 SectionIdentifierCheese = kSectionIdentifierEnumZero, |
| 36 SectionIdentifierWeasley, |
| 37 }; |
| 38 |
| 39 typedef NS_ENUM(NSInteger, ItemType) { |
| 40 ItemTypeCheeseHeader = kItemTypeEnumZero, |
| 41 ItemTypeCheeseCheddar, |
| 42 ItemTypeCheeseGouda, |
| 43 ItemTypeCheesePepperJack, |
| 44 ItemTypeWeasleyRon, |
| 45 ItemTypeWeasleyGinny, |
| 46 ItemTypeWeasleyArthur, |
| 47 ItemTypeWeasleyFooter, |
| 48 }; |
| 49 |
| 50 void LogSink(const std::string& str) { |
| 51 // No-op. |
| 52 } |
| 53 |
| 54 TEST(CollectionViewModelTest, EmptyModel) { |
| 55 base::scoped_nsobject<CollectionViewModel> model( |
| 56 [[CollectionViewModel alloc] init]); |
| 57 |
| 58 // Check there are no items. |
| 59 EXPECT_EQ(NO, [model hasItemAtIndexPath:[NSIndexPath indexPathForItem:0 |
| 60 inSection:0]]); |
| 61 |
| 62 // Check the collection view data sourcing methods. |
| 63 EXPECT_EQ(0, [model numberOfSections]); |
| 64 } |
| 65 |
| 66 TEST(CollectionViewModelTest, SingleSection) { |
| 67 base::scoped_nsobject<CollectionViewModel> model( |
| 68 [[CollectionViewModel alloc] init]); |
| 69 |
| 70 [model addSectionWithIdentifier:SectionIdentifierCheese]; |
| 71 [model addItemWithType:ItemTypeCheeseCheddar |
| 72 toSectionWithIdentifier:SectionIdentifierCheese]; |
| 73 [model addItemWithType:ItemTypeCheeseGouda |
| 74 toSectionWithIdentifier:SectionIdentifierCheese]; |
| 75 [model addItemWithType:ItemTypeCheesePepperJack |
| 76 toSectionWithIdentifier:SectionIdentifierCheese]; |
| 77 |
| 78 // Check there are some items but not more. |
| 79 EXPECT_EQ(YES, [model hasItemAtIndexPath:[NSIndexPath indexPathForItem:0 |
| 80 inSection:0]]); |
| 81 EXPECT_EQ(YES, [model hasItemAtIndexPath:[NSIndexPath indexPathForItem:2 |
| 82 inSection:0]]); |
| 83 EXPECT_EQ(NO, [model hasItemAtIndexPath:[NSIndexPath indexPathForItem:3 |
| 84 inSection:0]]); |
| 85 EXPECT_EQ(NO, [model hasItemAtIndexPath:[NSIndexPath indexPathForItem:0 |
| 86 inSection:1]]); |
| 87 |
| 88 // Check the collection view data sourcing methods. |
| 89 EXPECT_EQ(1, [model numberOfSections]); |
| 90 EXPECT_EQ(3, [model numberOfItemsInSection:0]); |
| 91 |
| 92 // Check the section identifier <-> section correspondance methods. |
| 93 EXPECT_EQ(SectionIdentifierCheese, [model sectionIdentifierForSection:0]); |
| 94 EXPECT_EQ(0, [model sectionForSectionIdentifier:SectionIdentifierCheese]); |
| 95 |
| 96 // Check the item type <-> item correspondance methods. |
| 97 EXPECT_EQ(ItemTypeCheeseCheddar, |
| 98 [model itemTypeForIndexPath:[NSIndexPath indexPathForItem:0 |
| 99 inSection:0]]); |
| 100 EXPECT_EQ(ItemTypeCheeseGouda, |
| 101 [model itemTypeForIndexPath:[NSIndexPath indexPathForItem:1 |
| 102 inSection:0]]); |
| 103 EXPECT_EQ(ItemTypeCheesePepperJack, |
| 104 [model itemTypeForIndexPath:[NSIndexPath indexPathForItem:2 |
| 105 inSection:0]]); |
| 106 } |
| 107 |
| 108 TEST(CollectionViewModelTest, SingleSectionWithMissingItems) { |
| 109 base::scoped_nsobject<CollectionViewModel> model( |
| 110 [[CollectionViewModel alloc] init]); |
| 111 |
| 112 [model addSectionWithIdentifier:SectionIdentifierCheese]; |
| 113 [model addItemWithType:ItemTypeCheeseCheddar |
| 114 toSectionWithIdentifier:SectionIdentifierCheese]; |
| 115 // "Gouda" is intentionally omitted. |
| 116 [model addItemWithType:ItemTypeCheesePepperJack |
| 117 toSectionWithIdentifier:SectionIdentifierCheese]; |
| 118 |
| 119 // Check the item type <-> item correspondance methods. |
| 120 EXPECT_EQ(ItemTypeCheeseCheddar, |
| 121 [model itemTypeForIndexPath:[NSIndexPath indexPathForItem:0 |
| 122 inSection:0]]); |
| 123 EXPECT_EQ(ItemTypeCheesePepperJack, |
| 124 [model itemTypeForIndexPath:[NSIndexPath indexPathForItem:1 |
| 125 inSection:0]]); |
| 126 } |
| 127 |
| 128 TEST(CollectionViewModelTest, MultipleSections) { |
| 129 base::scoped_nsobject<CollectionViewModel> model( |
| 130 [[CollectionViewModel alloc] init]); |
| 131 |
| 132 [model addSectionWithIdentifier:SectionIdentifierCheese]; |
| 133 // "Cheddar" and "Gouda" are intentionally omitted. |
| 134 [model addItemWithType:ItemTypeCheesePepperJack |
| 135 toSectionWithIdentifier:SectionIdentifierCheese]; |
| 136 |
| 137 [model addSectionWithIdentifier:SectionIdentifierWeasley]; |
| 138 // "Ron" is intentionally omitted. |
| 139 [model addItemWithType:ItemTypeWeasleyGinny |
| 140 toSectionWithIdentifier:SectionIdentifierWeasley]; |
| 141 [model addItemWithType:ItemTypeWeasleyArthur |
| 142 toSectionWithIdentifier:SectionIdentifierWeasley]; |
| 143 |
| 144 // Check the collection view data sourcing methods. |
| 145 EXPECT_EQ(2, [model numberOfSections]); |
| 146 EXPECT_EQ(2, [model numberOfItemsInSection:1]); |
| 147 |
| 148 // Check the section identifier <-> section correspondance methods. |
| 149 EXPECT_EQ(SectionIdentifierCheese, [model sectionIdentifierForSection:0]); |
| 150 EXPECT_EQ(0, [model sectionForSectionIdentifier:SectionIdentifierCheese]); |
| 151 EXPECT_EQ(SectionIdentifierWeasley, [model sectionIdentifierForSection:1]); |
| 152 EXPECT_EQ(1, [model sectionForSectionIdentifier:SectionIdentifierWeasley]); |
| 153 |
| 154 // Check the item type <-> item correspondance methods. |
| 155 EXPECT_EQ(ItemTypeCheesePepperJack, |
| 156 [model itemTypeForIndexPath:[NSIndexPath indexPathForItem:0 |
| 157 inSection:0]]); |
| 158 EXPECT_EQ(ItemTypeWeasleyGinny, |
| 159 [model itemTypeForIndexPath:[NSIndexPath indexPathForItem:0 |
| 160 inSection:1]]); |
| 161 EXPECT_EQ(ItemTypeWeasleyArthur, |
| 162 [model itemTypeForIndexPath:[NSIndexPath indexPathForItem:1 |
| 163 inSection:1]]); |
| 164 } |
| 165 |
| 166 TEST(CollectionViewModelTest, GetIndexPathFromModelCoordinates) { |
| 167 base::scoped_nsobject<CollectionViewModel> model( |
| 168 [[CollectionViewModel alloc] init]); |
| 169 |
| 170 [model addSectionWithIdentifier:SectionIdentifierCheese]; |
| 171 [model addItemWithType:ItemTypeCheesePepperJack |
| 172 toSectionWithIdentifier:SectionIdentifierCheese]; |
| 173 [model addSectionWithIdentifier:SectionIdentifierWeasley]; |
| 174 [model addItemWithType:ItemTypeWeasleyGinny |
| 175 toSectionWithIdentifier:SectionIdentifierWeasley]; |
| 176 [model addItemWithType:ItemTypeWeasleyArthur |
| 177 toSectionWithIdentifier:SectionIdentifierWeasley]; |
| 178 |
| 179 // Check the index path retrieval method for a single item. |
| 180 NSIndexPath* indexPath = |
| 181 [model indexPathForItemType:ItemTypeWeasleyGinny |
| 182 sectionIdentifier:SectionIdentifierWeasley]; |
| 183 EXPECT_EQ(1, indexPath.section); |
| 184 EXPECT_EQ(0, indexPath.item); |
| 185 |
| 186 // Check the index path retrieval method for the first item. |
| 187 indexPath = [model indexPathForItemType:ItemTypeWeasleyGinny |
| 188 sectionIdentifier:SectionIdentifierWeasley |
| 189 atIndex:0]; |
| 190 EXPECT_EQ(1, indexPath.section); |
| 191 EXPECT_EQ(0, indexPath.item); |
| 192 } |
| 193 |
| 194 TEST(CollectionViewItemTest, RepeatedItems) { |
| 195 base::scoped_nsobject<CollectionViewModel> model( |
| 196 [[CollectionViewModel alloc] init]); |
| 197 |
| 198 [model addSectionWithIdentifier:SectionIdentifierCheese]; |
| 199 [model addItemWithType:ItemTypeCheesePepperJack |
| 200 toSectionWithIdentifier:SectionIdentifierCheese]; |
| 201 [model addSectionWithIdentifier:SectionIdentifierWeasley]; |
| 202 [model addItemWithType:ItemTypeWeasleyGinny |
| 203 toSectionWithIdentifier:SectionIdentifierWeasley]; |
| 204 [model addItemWithType:ItemTypeWeasleyArthur |
| 205 toSectionWithIdentifier:SectionIdentifierWeasley]; |
| 206 [model addItemWithType:ItemTypeWeasleyArthur |
| 207 toSectionWithIdentifier:SectionIdentifierWeasley]; |
| 208 [model addItemWithType:ItemTypeWeasleyArthur |
| 209 toSectionWithIdentifier:SectionIdentifierWeasley]; |
| 210 |
| 211 NSIndexPath* indexPath = |
| 212 [model indexPathForItemType:ItemTypeWeasleyArthur |
| 213 sectionIdentifier:SectionIdentifierWeasley]; |
| 214 |
| 215 // Check the index path retrieval method for a single item on a repeated item. |
| 216 EXPECT_EQ(1, indexPath.section); |
| 217 EXPECT_EQ(1, indexPath.item); |
| 218 |
| 219 // Check the index path retrieval method for a repeated item. |
| 220 indexPath = [model indexPathForItemType:ItemTypeWeasleyArthur |
| 221 sectionIdentifier:SectionIdentifierWeasley |
| 222 atIndex:1]; |
| 223 |
| 224 EXPECT_EQ(1, indexPath.section); |
| 225 EXPECT_EQ(2, indexPath.item); |
| 226 } |
| 227 |
| 228 TEST(CollectionViewModelTest, RepeatedItemIndex) { |
| 229 base::scoped_nsobject<CollectionViewModel> model( |
| 230 [[CollectionViewModel alloc] init]); |
| 231 |
| 232 [model addSectionWithIdentifier:SectionIdentifierCheese]; |
| 233 [model addItemWithType:ItemTypeCheesePepperJack |
| 234 toSectionWithIdentifier:SectionIdentifierCheese]; |
| 235 [model addSectionWithIdentifier:SectionIdentifierWeasley]; |
| 236 [model addItemWithType:ItemTypeWeasleyGinny |
| 237 toSectionWithIdentifier:SectionIdentifierWeasley]; |
| 238 [model addItemWithType:ItemTypeWeasleyArthur |
| 239 toSectionWithIdentifier:SectionIdentifierWeasley]; |
| 240 [model addItemWithType:ItemTypeWeasleyArthur |
| 241 toSectionWithIdentifier:SectionIdentifierWeasley]; |
| 242 [model addItemWithType:ItemTypeWeasleyArthur |
| 243 toSectionWithIdentifier:SectionIdentifierWeasley]; |
| 244 [model addItemWithType:ItemTypeWeasleyGinny |
| 245 toSectionWithIdentifier:SectionIdentifierWeasley]; |
| 246 [model addItemWithType:ItemTypeWeasleyArthur |
| 247 toSectionWithIdentifier:SectionIdentifierWeasley]; |
| 248 |
| 249 // Check the index path <-> index in item type correspondance method. |
| 250 EXPECT_EQ( |
| 251 0U, [model indexInItemTypeForIndexPath:[NSIndexPath indexPathForItem:0 |
| 252 inSection:0]]); |
| 253 EXPECT_EQ( |
| 254 0U, [model indexInItemTypeForIndexPath:[NSIndexPath indexPathForItem:1 |
| 255 inSection:1]]); |
| 256 EXPECT_EQ( |
| 257 2U, [model indexInItemTypeForIndexPath:[NSIndexPath indexPathForItem:3 |
| 258 inSection:1]]); |
| 259 EXPECT_EQ( |
| 260 3U, [model indexInItemTypeForIndexPath:[NSIndexPath indexPathForItem:5 |
| 261 inSection:1]]); |
| 262 } |
| 263 |
| 264 TEST(CollectionViewModelTest, RetrieveAddedItem) { |
| 265 base::scoped_nsobject<CollectionViewModel> model( |
| 266 [[CollectionViewModel alloc] init]); |
| 267 |
| 268 [model addSectionWithIdentifier:SectionIdentifierCheese]; |
| 269 base::scoped_nsobject<CollectionViewItem> someItem( |
| 270 [[CollectionViewItem alloc] initWithType:ItemTypeCheeseGouda]); |
| 271 [model addItem:someItem toSectionWithIdentifier:SectionIdentifierCheese]; |
| 272 |
| 273 // Check that the item is the same in the model. |
| 274 EXPECT_EQ(someItem, [model itemAtIndexPath:[NSIndexPath indexPathForItem:0 |
| 275 inSection:0]]); |
| 276 } |
| 277 |
| 278 TEST(CollectionViewModelTest, RetrieveItemsInSection) { |
| 279 base::scoped_nsobject<CollectionViewModel> model( |
| 280 [[CollectionViewModel alloc] init]); |
| 281 [model addSectionWithIdentifier:SectionIdentifierCheese]; |
| 282 base::scoped_nsobject<CollectionViewItem> cheddar( |
| 283 [[CollectionViewItem alloc] initWithType:ItemTypeCheeseCheddar]); |
| 284 [model addItem:cheddar toSectionWithIdentifier:SectionIdentifierCheese]; |
| 285 base::scoped_nsobject<CollectionViewItem> pepperJack( |
| 286 [[CollectionViewItem alloc] initWithType:ItemTypeCheesePepperJack]); |
| 287 [model addItem:pepperJack toSectionWithIdentifier:SectionIdentifierCheese]; |
| 288 base::scoped_nsobject<CollectionViewItem> gouda( |
| 289 [[CollectionViewItem alloc] initWithType:ItemTypeCheeseGouda]); |
| 290 [model addItem:gouda toSectionWithIdentifier:SectionIdentifierCheese]; |
| 291 |
| 292 NSArray* cheeseItems = |
| 293 [model itemsInSectionWithIdentifier:SectionIdentifierCheese]; |
| 294 EXPECT_EQ(3U, [cheeseItems count]); |
| 295 EXPECT_NSEQ(cheddar, cheeseItems[0]); |
| 296 EXPECT_NSEQ(pepperJack, cheeseItems[1]); |
| 297 EXPECT_NSEQ(gouda, cheeseItems[2]); |
| 298 } |
| 299 |
| 300 TEST(CollectionViewModelTest, InvalidIndexPath) { |
| 301 base::scoped_nsobject<CollectionViewModel> model( |
| 302 [[CollectionViewModel alloc] init]); |
| 303 [model addSectionWithIdentifier:SectionIdentifierCheese]; |
| 304 |
| 305 bool out_of_bounds_exception_thrown = false; |
| 306 @try { |
| 307 logging::SetLogAssertHandler(&LogSink); |
| 308 [model indexInItemTypeForIndexPath:[NSIndexPath indexPathForItem:0 |
| 309 inSection:0]]; |
| 310 } @catch (NSException* exception) { |
| 311 if ([[exception name] isEqualToString:NSRangeException]) { |
| 312 out_of_bounds_exception_thrown = true; |
| 313 } |
| 314 } |
| 315 EXPECT_TRUE(out_of_bounds_exception_thrown); |
| 316 } |
| 317 |
| 318 TEST(CollectionViewModelTest, RemoveItems) { |
| 319 base::scoped_nsobject<CollectionViewModel> model( |
| 320 [[CollectionViewModel alloc] init]); |
| 321 |
| 322 [model addSectionWithIdentifier:SectionIdentifierCheese]; |
| 323 [model addItemWithType:ItemTypeCheesePepperJack |
| 324 toSectionWithIdentifier:SectionIdentifierCheese]; |
| 325 [model addItemWithType:ItemTypeCheeseGouda |
| 326 toSectionWithIdentifier:SectionIdentifierCheese]; |
| 327 |
| 328 [model addSectionWithIdentifier:SectionIdentifierWeasley]; |
| 329 [model addItemWithType:ItemTypeWeasleyGinny |
| 330 toSectionWithIdentifier:SectionIdentifierWeasley]; |
| 331 [model addItemWithType:ItemTypeWeasleyArthur |
| 332 toSectionWithIdentifier:SectionIdentifierWeasley]; |
| 333 [model addItemWithType:ItemTypeWeasleyArthur |
| 334 toSectionWithIdentifier:SectionIdentifierWeasley]; |
| 335 [model addItemWithType:ItemTypeWeasleyArthur |
| 336 toSectionWithIdentifier:SectionIdentifierWeasley]; |
| 337 [model addItemWithType:ItemTypeWeasleyRon |
| 338 toSectionWithIdentifier:SectionIdentifierWeasley]; |
| 339 |
| 340 [model removeItemWithType:ItemTypeCheesePepperJack |
| 341 fromSectionWithIdentifier:SectionIdentifierCheese]; |
| 342 [model removeItemWithType:ItemTypeWeasleyGinny |
| 343 fromSectionWithIdentifier:SectionIdentifierWeasley]; |
| 344 [model removeItemWithType:ItemTypeWeasleyArthur |
| 345 fromSectionWithIdentifier:SectionIdentifierWeasley |
| 346 atIndex:2]; |
| 347 |
| 348 // Check the collection view data sourcing methods. |
| 349 EXPECT_EQ(2, [model numberOfSections]); |
| 350 |
| 351 // Check the index path retrieval method for a single item. |
| 352 NSIndexPath* indexPath = [model indexPathForItemType:ItemTypeCheeseGouda |
| 353 sectionIdentifier:SectionIdentifierCheese]; |
| 354 EXPECT_EQ(0, indexPath.section); |
| 355 EXPECT_EQ(0, indexPath.item); |
| 356 |
| 357 // Check the index path retrieval method for a repeated item. |
| 358 indexPath = [model indexPathForItemType:ItemTypeWeasleyArthur |
| 359 sectionIdentifier:SectionIdentifierWeasley |
| 360 atIndex:1]; |
| 361 EXPECT_EQ(1, indexPath.section); |
| 362 EXPECT_EQ(1, indexPath.item); |
| 363 |
| 364 // Check the index path retrieval method for a single item. |
| 365 indexPath = [model indexPathForItemType:ItemTypeWeasleyRon |
| 366 sectionIdentifier:SectionIdentifierWeasley]; |
| 367 EXPECT_EQ(1, indexPath.section); |
| 368 EXPECT_EQ(2, indexPath.item); |
| 369 } |
| 370 |
| 371 TEST(CollectionViewModelTest, RemoveSections) { |
| 372 base::scoped_nsobject<CollectionViewModel> model( |
| 373 [[CollectionViewModel alloc] init]); |
| 374 |
| 375 // Empty section. |
| 376 [model addSectionWithIdentifier:SectionIdentifierWeasley]; |
| 377 |
| 378 // Section with items. |
| 379 [model addSectionWithIdentifier:SectionIdentifierCheese]; |
| 380 [model addItemWithType:ItemTypeCheesePepperJack |
| 381 toSectionWithIdentifier:SectionIdentifierCheese]; |
| 382 [model addItemWithType:ItemTypeCheeseGouda |
| 383 toSectionWithIdentifier:SectionIdentifierCheese]; |
| 384 |
| 385 // Check the collection view data sourcing methods. |
| 386 EXPECT_EQ(2, [model numberOfSections]); |
| 387 EXPECT_EQ(0, [model numberOfItemsInSection:0]); |
| 388 EXPECT_EQ(2, [model numberOfItemsInSection:1]); |
| 389 |
| 390 // Remove an empty section. |
| 391 [model removeSectionWithIdentifier:SectionIdentifierWeasley]; |
| 392 |
| 393 // Check that the section was removed. |
| 394 EXPECT_EQ(1, [model numberOfSections]); |
| 395 EXPECT_EQ(2, [model numberOfItemsInSection:0]); |
| 396 |
| 397 // Remove a section with items. |
| 398 [model removeSectionWithIdentifier:SectionIdentifierCheese]; |
| 399 |
| 400 // Check that the section and its items were removed. |
| 401 EXPECT_EQ(0, [model numberOfSections]); |
| 402 } |
| 403 |
| 404 TEST(CollectionViewModelTest, QueryItemsFromModelCoordinates) { |
| 405 base::scoped_nsobject<CollectionViewModel> model( |
| 406 [[CollectionViewModel alloc] init]); |
| 407 |
| 408 EXPECT_FALSE([model hasSectionForSectionIdentifier:SectionIdentifierWeasley]); |
| 409 EXPECT_FALSE([model hasItemForItemType:ItemTypeCheeseCheddar |
| 410 sectionIdentifier:SectionIdentifierCheese]); |
| 411 EXPECT_FALSE([model hasItemForItemType:ItemTypeCheeseGouda |
| 412 sectionIdentifier:SectionIdentifierCheese |
| 413 atIndex:1]); |
| 414 |
| 415 // Section with items. |
| 416 [model addSectionWithIdentifier:SectionIdentifierCheese]; |
| 417 [model addItemWithType:ItemTypeCheesePepperJack |
| 418 toSectionWithIdentifier:SectionIdentifierCheese]; |
| 419 [model addItemWithType:ItemTypeCheeseGouda |
| 420 toSectionWithIdentifier:SectionIdentifierCheese]; |
| 421 [model addItemWithType:ItemTypeCheeseGouda |
| 422 toSectionWithIdentifier:SectionIdentifierCheese]; |
| 423 |
| 424 EXPECT_TRUE([model hasSectionForSectionIdentifier:SectionIdentifierCheese]); |
| 425 EXPECT_FALSE([model hasItemForItemType:ItemTypeCheeseCheddar |
| 426 sectionIdentifier:SectionIdentifierCheese]); |
| 427 EXPECT_TRUE([model hasItemForItemType:ItemTypeCheesePepperJack |
| 428 sectionIdentifier:SectionIdentifierCheese]); |
| 429 EXPECT_TRUE([model hasItemForItemType:ItemTypeCheeseGouda |
| 430 sectionIdentifier:SectionIdentifierCheese |
| 431 atIndex:1]); |
| 432 } |
| 433 |
| 434 // Tests that inserted sections are added at the correct index. |
| 435 TEST(CollectionViewModelTest, InsertSections) { |
| 436 base::scoped_nsobject<CollectionViewModel> model( |
| 437 [[CollectionViewModel alloc] init]); |
| 438 |
| 439 [model addSectionWithIdentifier:SectionIdentifierWeasley]; |
| 440 EXPECT_EQ(1, [model numberOfSections]); |
| 441 EXPECT_EQ(0, [model sectionForSectionIdentifier:SectionIdentifierWeasley]); |
| 442 |
| 443 [model insertSectionWithIdentifier:SectionIdentifierCheese atIndex:0]; |
| 444 EXPECT_EQ(2, [model numberOfSections]); |
| 445 EXPECT_EQ(1, [model sectionForSectionIdentifier:SectionIdentifierWeasley]); |
| 446 EXPECT_EQ(0, [model sectionForSectionIdentifier:SectionIdentifierCheese]); |
| 447 |
| 448 [model removeSectionWithIdentifier:SectionIdentifierCheese]; |
| 449 [model insertSectionWithIdentifier:SectionIdentifierCheese atIndex:1]; |
| 450 EXPECT_EQ(2, [model numberOfSections]); |
| 451 EXPECT_EQ(0, [model sectionForSectionIdentifier:SectionIdentifierWeasley]); |
| 452 EXPECT_EQ(1, [model sectionForSectionIdentifier:SectionIdentifierCheese]); |
| 453 } |
| 454 |
| 455 // Tests that inserted items are added at the correct index. |
| 456 TEST(CollectionViewModelTest, InsertItemAtIndex) { |
| 457 base::scoped_nsobject<CollectionViewModel> model( |
| 458 [[CollectionViewModel alloc] init]); |
| 459 |
| 460 [model addSectionWithIdentifier:SectionIdentifierCheese]; |
| 461 [model addItemWithType:ItemTypeCheesePepperJack |
| 462 toSectionWithIdentifier:SectionIdentifierCheese]; |
| 463 [model addItemWithType:ItemTypeCheeseGouda |
| 464 toSectionWithIdentifier:SectionIdentifierCheese]; |
| 465 base::scoped_nsobject<CollectionViewItem> cheddarItem( |
| 466 [[CollectionViewItem alloc] initWithType:ItemTypeCheeseCheddar]); |
| 467 [model insertItem:cheddarItem |
| 468 inSectionWithIdentifier:SectionIdentifierCheese |
| 469 atIndex:1]; |
| 470 |
| 471 EXPECT_EQ(1, [model numberOfSections]); |
| 472 |
| 473 NSIndexPath* pepperJackIndexPath = |
| 474 [model indexPathForItemType:ItemTypeCheesePepperJack |
| 475 sectionIdentifier:SectionIdentifierCheese]; |
| 476 EXPECT_EQ(0, pepperJackIndexPath.section); |
| 477 EXPECT_EQ(0, pepperJackIndexPath.item); |
| 478 |
| 479 NSIndexPath* cheddarIndexPath = |
| 480 [model indexPathForItemType:ItemTypeCheeseCheddar |
| 481 sectionIdentifier:SectionIdentifierCheese]; |
| 482 EXPECT_EQ(0, cheddarIndexPath.section); |
| 483 EXPECT_EQ(1, cheddarIndexPath.item); |
| 484 |
| 485 NSIndexPath* goudaIndexPath = |
| 486 [model indexPathForItemType:ItemTypeCheeseGouda |
| 487 sectionIdentifier:SectionIdentifierCheese]; |
| 488 EXPECT_EQ(0, goudaIndexPath.section); |
| 489 EXPECT_EQ(2, goudaIndexPath.item); |
| 490 } |
| 491 |
| 492 TEST(CollectionViewModelTest, IndexPathsForItems) { |
| 493 base::scoped_nsobject<CollectionViewModel> model( |
| 494 [[CollectionViewModel alloc] init]); |
| 495 |
| 496 [model addSectionWithIdentifier:SectionIdentifierWeasley]; |
| 497 [model addItemWithType:ItemTypeWeasleyGinny |
| 498 toSectionWithIdentifier:SectionIdentifierWeasley]; |
| 499 // Added at index 1. |
| 500 base::scoped_nsobject<CollectionViewItem> item1( |
| 501 [[CollectionViewItem alloc] initWithType:ItemTypeWeasleyRon]); |
| 502 [model addItem:item1 toSectionWithIdentifier:SectionIdentifierWeasley]; |
| 503 [model addItemWithType:ItemTypeWeasleyGinny |
| 504 toSectionWithIdentifier:SectionIdentifierWeasley]; |
| 505 [model addItemWithType:ItemTypeWeasleyArthur |
| 506 toSectionWithIdentifier:SectionIdentifierWeasley]; |
| 507 // Repeated item added at index 4. |
| 508 base::scoped_nsobject<CollectionViewItem> item4( |
| 509 [[CollectionViewItem alloc] initWithType:ItemTypeWeasleyArthur]); |
| 510 [model addItem:item4 toSectionWithIdentifier:SectionIdentifierWeasley]; |
| 511 [model addItemWithType:ItemTypeWeasleyArthur |
| 512 toSectionWithIdentifier:SectionIdentifierWeasley]; |
| 513 [model addItemWithType:ItemTypeWeasleyArthur |
| 514 toSectionWithIdentifier:SectionIdentifierWeasley]; |
| 515 |
| 516 NSIndexPath* indexPath1 = [model indexPathForItem:item1 |
| 517 inSectionWithIdentifier:SectionIdentifierWeasley]; |
| 518 EXPECT_EQ(0, indexPath1.section); |
| 519 EXPECT_EQ(1, indexPath1.item); |
| 520 |
| 521 NSIndexPath* indexPath4 = [model indexPathForItem:item4 |
| 522 inSectionWithIdentifier:SectionIdentifierWeasley]; |
| 523 EXPECT_EQ(0, indexPath4.section); |
| 524 EXPECT_EQ(4, indexPath4.item); |
| 525 } |
| 526 |
| 527 TEST(CollectionViewModelTest, Headers) { |
| 528 base::scoped_nsobject<CollectionViewModel> model( |
| 529 [[CollectionViewModel alloc] init]); |
| 530 |
| 531 [model addSectionWithIdentifier:SectionIdentifierCheese]; |
| 532 base::scoped_nsobject<CollectionViewItem> cheeseHeader( |
| 533 [[CollectionViewItem alloc] initWithType:ItemTypeCheeseHeader]); |
| 534 [model setHeader:cheeseHeader |
| 535 forSectionWithIdentifier:SectionIdentifierCheese]; |
| 536 [model addItemWithType:ItemTypeCheeseGouda |
| 537 toSectionWithIdentifier:SectionIdentifierCheese]; |
| 538 [model addItemWithType:ItemTypeCheeseCheddar |
| 539 toSectionWithIdentifier:SectionIdentifierCheese]; |
| 540 [model addSectionWithIdentifier:SectionIdentifierWeasley]; |
| 541 [model addItemWithType:ItemTypeWeasleyRon |
| 542 toSectionWithIdentifier:SectionIdentifierWeasley]; |
| 543 [model addItemWithType:ItemTypeWeasleyGinny |
| 544 toSectionWithIdentifier:SectionIdentifierWeasley]; |
| 545 |
| 546 NSInteger cheeseSection = |
| 547 [model sectionForSectionIdentifier:SectionIdentifierCheese]; |
| 548 NSInteger weasleySection = |
| 549 [model sectionForSectionIdentifier:SectionIdentifierWeasley]; |
| 550 |
| 551 EXPECT_EQ(cheeseHeader.get(), |
| 552 [model headerForSectionWithIdentifier:SectionIdentifierCheese]); |
| 553 EXPECT_EQ(cheeseHeader.get(), [model headerForSection:cheeseSection]); |
| 554 |
| 555 EXPECT_FALSE([model headerForSectionWithIdentifier:SectionIdentifierWeasley]); |
| 556 EXPECT_FALSE([model headerForSection:weasleySection]); |
| 557 } |
| 558 |
| 559 TEST(CollectionViewModelTest, Footers) { |
| 560 base::scoped_nsobject<CollectionViewModel> model( |
| 561 [[CollectionViewModel alloc] init]); |
| 562 |
| 563 [model addSectionWithIdentifier:SectionIdentifierCheese]; |
| 564 [model addItemWithType:ItemTypeCheeseGouda |
| 565 toSectionWithIdentifier:SectionIdentifierCheese]; |
| 566 [model addItemWithType:ItemTypeCheeseCheddar |
| 567 toSectionWithIdentifier:SectionIdentifierCheese]; |
| 568 [model addSectionWithIdentifier:SectionIdentifierWeasley]; |
| 569 [model addItemWithType:ItemTypeWeasleyRon |
| 570 toSectionWithIdentifier:SectionIdentifierWeasley]; |
| 571 [model addItemWithType:ItemTypeWeasleyGinny |
| 572 toSectionWithIdentifier:SectionIdentifierWeasley]; |
| 573 base::scoped_nsobject<CollectionViewItem> weasleyFooter( |
| 574 [[CollectionViewItem alloc] initWithType:ItemTypeWeasleyFooter]); |
| 575 [model setFooter:weasleyFooter |
| 576 forSectionWithIdentifier:SectionIdentifierWeasley]; |
| 577 |
| 578 NSInteger cheeseSection = |
| 579 [model sectionForSectionIdentifier:SectionIdentifierCheese]; |
| 580 NSInteger weasleySection = |
| 581 [model sectionForSectionIdentifier:SectionIdentifierWeasley]; |
| 582 |
| 583 EXPECT_FALSE([model footerForSectionWithIdentifier:SectionIdentifierCheese]); |
| 584 EXPECT_FALSE([model footerForSection:cheeseSection]); |
| 585 |
| 586 EXPECT_EQ(weasleyFooter.get(), |
| 587 [model footerForSectionWithIdentifier:SectionIdentifierWeasley]); |
| 588 EXPECT_EQ(weasleyFooter.get(), [model footerForSection:weasleySection]); |
| 589 } |
| 590 |
| 591 } // namespace |
OLD | NEW |