apps_grid_controller_unittest.mm revision c2e0dbddbe15c98d52c4786dac06cb8952a8ae6d
1// Copyright 2013 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#include "base/memory/scoped_nsobject.h" 6#import "testing/gtest_mac.h" 7#include "ui/app_list/app_list_item_model.h" 8#import "ui/app_list/cocoa/apps_collection_view_drag_manager.h" 9#import "ui/app_list/cocoa/apps_grid_controller.h" 10#import "ui/app_list/cocoa/apps_grid_view_item.h" 11#import "ui/app_list/cocoa/apps_pagination_model_observer.h" 12#import "ui/app_list/cocoa/test/apps_grid_controller_test_helper.h" 13#include "ui/app_list/test/app_list_test_model.h" 14#include "ui/app_list/test/app_list_test_view_delegate.h" 15#import "ui/base/test/cocoa_test_event_utils.h" 16 17@interface TestPaginationObserver : NSObject<AppsPaginationModelObserver> { 18 @private 19 int totalPagesChangedCount_; 20 int selectedPageChangedCount_; 21 int lastNewSelectedPage_; 22} 23 24@property(assign, nonatomic) int totalPagesChangedCount; 25@property(assign, nonatomic) int selectedPageChangedCount; 26@property(assign, nonatomic) int lastNewSelectedPage; 27 28@end 29 30@implementation TestPaginationObserver 31 32@synthesize totalPagesChangedCount = totalPagesChangedCount_; 33@synthesize selectedPageChangedCount = selectedPageChangedCount_; 34@synthesize lastNewSelectedPage = lastNewSelectedPage_; 35 36- (void)totalPagesChanged { 37 ++totalPagesChangedCount_; 38} 39 40- (void)selectedPageChanged:(int)newSelected { 41 ++selectedPageChangedCount_; 42 lastNewSelectedPage_ = newSelected; 43} 44 45@end 46 47namespace app_list { 48namespace test { 49 50namespace { 51 52class AppsGridControllerTest : public AppsGridControllerTestHelper { 53 public: 54 AppsGridControllerTest() {} 55 56 virtual void SetUp() OVERRIDE { 57 owned_apps_grid_controller_.reset([[AppsGridController alloc] init]); 58 [owned_apps_grid_controller_ setDelegate:delegate_.get()]; 59 AppsGridControllerTestHelper::SetUpWithGridController( 60 owned_apps_grid_controller_.get()); 61 62 [[test_window() contentView] addSubview:[apps_grid_controller_ view]]; 63 [test_window() makePretendKeyWindowAndSetFirstResponder: 64 [apps_grid_controller_ collectionViewAtPageIndex:0]]; 65 } 66 67 virtual void TearDown() OVERRIDE { 68 owned_apps_grid_controller_.reset(); 69 AppsGridControllerTestHelper::TearDown(); 70 } 71 72 private: 73 scoped_nsobject<AppsGridController> owned_apps_grid_controller_; 74 75 DISALLOW_COPY_AND_ASSIGN(AppsGridControllerTest); 76}; 77 78} // namespace 79 80TEST_VIEW(AppsGridControllerTest, [apps_grid_controller_ view]); 81 82// Test showing with an empty model. 83TEST_F(AppsGridControllerTest, EmptyModelAndShow) { 84 EXPECT_TRUE([[apps_grid_controller_ view] superview]); 85 86 // First page should always exist, even if empty. 87 EXPECT_EQ(1u, [apps_grid_controller_ pageCount]); 88 EXPECT_EQ(0u, [[GetPageAt(0) content] count]); 89 EXPECT_TRUE([GetPageAt(0) superview]); // The pages container. 90 EXPECT_TRUE([[GetPageAt(0) superview] superview]); 91} 92 93// Test with a single item. 94// This test is disabled in builders until the delay to wait for the collection 95// view to load subviews can be removed, or some other solution is found. 96TEST_F(AppsGridControllerTest, DISABLED_SingleEntryModel) { 97 // We need to "wake up" the NSCollectionView, otherwise it does not 98 // immediately update its subviews later in this function. 99 // When this test is run by itself, it's enough just to send a keypress (and 100 // this delay is not needed). 101 DelayForCollectionView(); 102 EXPECT_EQ(1u, [apps_grid_controller_ pageCount]); 103 EXPECT_EQ(0u, [[GetPageAt(0) content] count]); 104 105 model()->PopulateApps(1); 106 SinkEvents(); 107 EXPECT_FALSE([GetPageAt(0) animations]); 108 109 EXPECT_EQ(1u, [[GetPageAt(0) content] count]); 110 NSArray* subviews = [GetPageAt(0) subviews]; 111 EXPECT_EQ(1u, [subviews count]); 112 113 // Note that using GetItemViewAt(0) here also works, and returns non-nil even 114 // without the delay, but a "click" on it does not register without the delay. 115 NSView* subview = [subviews objectAtIndex:0]; 116 117 // Launch the item. 118 SimulateClick(subview); 119 SinkEvents(); 120 EXPECT_EQ(1, delegate()->activate_count()); 121 EXPECT_EQ(std::string("Item 0"), delegate()->last_activated()->title()); 122} 123 124// Test activating an item on the second page (the 17th item). 125TEST_F(AppsGridControllerTest, DISABLED_TwoPageModel) { 126 DelayForCollectionView(); 127 ReplaceTestModel(kItemsPerPage * 2); 128 [apps_grid_controller_ scrollToPage:1]; 129 130 // The NSScrollView animator ignores the duration configured on the 131 // NSAnimationContext (set by CocoaTest::Init), so we need to delay here. 132 DelayForCollectionView(); 133 NSArray* subviews = [GetPageAt(1) subviews]; 134 NSView* subview = [subviews objectAtIndex:0]; 135 // Launch the item. 136 SimulateClick(subview); 137 SinkEvents(); 138 EXPECT_EQ(1, delegate()->activate_count()); 139 EXPECT_EQ(std::string("Item 16"), delegate()->last_activated()->title()); 140} 141 142// Test setModel. 143TEST_F(AppsGridControllerTest, ReplaceModel) { 144 const size_t kOrigItems = 1; 145 const size_t kNewItems = 2; 146 147 model()->PopulateApps(kOrigItems); 148 EXPECT_EQ(kOrigItems, [[GetPageAt(0) content] count]); 149 150 ReplaceTestModel(kNewItems); 151 EXPECT_EQ(kNewItems, [[GetPageAt(0) content] count]); 152} 153 154// Test pagination. 155TEST_F(AppsGridControllerTest, Pagination) { 156 model()->PopulateApps(1); 157 EXPECT_EQ(1u, [apps_grid_controller_ pageCount]); 158 EXPECT_EQ(1u, [[GetPageAt(0) content] count]); 159 160 ReplaceTestModel(kItemsPerPage); 161 EXPECT_EQ(1u, [apps_grid_controller_ pageCount]); 162 EXPECT_EQ(kItemsPerPage, [[GetPageAt(0) content] count]); 163 164 // Test adding an item onto the next page. 165 model()->PopulateApps(1); // Now 17 items. 166 EXPECT_EQ(2u, [apps_grid_controller_ pageCount]); 167 EXPECT_EQ(kItemsPerPage, [[GetPageAt(0) content] count]); 168 EXPECT_EQ(1u, [[GetPageAt(1) content] count]); 169 170 // Test N pages with the last page having one empty spot. 171 const size_t kPagesToTest = 3; 172 ReplaceTestModel(kPagesToTest * kItemsPerPage - 1); 173 EXPECT_EQ(kPagesToTest, [apps_grid_controller_ pageCount]); 174 for (size_t page_index = 0; page_index < kPagesToTest - 1; ++page_index) { 175 EXPECT_EQ(kItemsPerPage, [[GetPageAt(page_index) content] count]); 176 } 177 EXPECT_EQ(kItemsPerPage - 1, [[GetPageAt(kPagesToTest - 1) content] count]); 178 179 // Test removing pages. 180 ReplaceTestModel(1); 181 EXPECT_EQ(1u, [apps_grid_controller_ pageCount]); 182 EXPECT_EQ(1u, [[GetPageAt(0) content] count]); 183} 184 185// Tests basic left-right keyboard navigation on the first page, later tests 186// will test keyboard navigation across pages and other corner cases. 187TEST_F(AppsGridControllerTest, DISABLED_FirstPageKeyboardNavigation) { 188 model()->PopulateApps(3); 189 SinkEvents(); 190 EXPECT_EQ(3u, [[GetPageAt(0) content] count]); 191 192 SimulateKeyPress(NSRightArrowFunctionKey); 193 SinkEvents(); 194 EXPECT_EQ(GetSelectedView(), GetItemViewAt(0)); 195 196 SimulateKeyPress(NSRightArrowFunctionKey); 197 SinkEvents(); 198 EXPECT_EQ(GetSelectedView(), GetItemViewAt(1)); 199 200 SimulateKeyPress(NSLeftArrowFunctionKey); 201 SinkEvents(); 202 EXPECT_EQ(GetSelectedView(), GetItemViewAt(0)); 203 204 // Go to the last item, and launch it. 205 SimulateKeyPress(NSRightArrowFunctionKey); 206 SimulateKeyPress(NSRightArrowFunctionKey); 207 [apps_grid_controller_ activateSelection]; 208 SinkEvents(); 209 EXPECT_EQ(GetSelectedView(), GetItemViewAt(2)); 210 EXPECT_EQ(1, delegate()->activate_count()); 211 EXPECT_EQ(std::string("Item 2"), delegate()->last_activated()->title()); 212} 213 214// Test runtime updates: adding items, changing titles and icons. 215TEST_F(AppsGridControllerTest, ModelUpdates) { 216 model()->PopulateApps(2); 217 EXPECT_EQ(2u, [[GetPageAt(0) content] count]); 218 219 // Add an item (PopulateApps will create a duplicate "Item 0"). 220 model()->PopulateApps(1); 221 EXPECT_EQ(3u, [[GetPageAt(0) content] count]); 222 NSButton* button = GetItemViewAt(2); 223 EXPECT_NSEQ(@"Item 0", [button title]); 224 225 // Update the title via the ItemModelObserver. 226 app_list::AppListItemModel* item_model = model()->apps()->GetItemAt(2); 227 item_model->SetTitle("UpdatedItem"); 228 EXPECT_NSEQ(@"UpdatedItem", [button title]); 229 230 // Update the icon, test by changing size. 231 NSSize icon_size = [[button image] size]; 232 EXPECT_EQ(0, icon_size.width); 233 EXPECT_EQ(0, icon_size.height); 234 235 SkBitmap bitmap; 236 const int kTestImageSize = 10; 237 bitmap.setConfig(SkBitmap::kARGB_8888_Config, kTestImageSize, kTestImageSize); 238 item_model->SetIcon(gfx::ImageSkia::CreateFrom1xBitmap(bitmap), false); 239 icon_size = [[button image] size]; 240 EXPECT_EQ(kTestImageSize, icon_size.width); 241 EXPECT_EQ(kTestImageSize, icon_size.height); 242} 243 244// Test mouseover selection. 245TEST_F(AppsGridControllerTest, MouseoverSelects) { 246 model()->PopulateApps(2); 247 EXPECT_EQ(nil, GetSelectedView()); 248 249 // Test entering and exiting the first item. 250 SimulateMouseEnterItemAt(0); 251 EXPECT_EQ(GetItemViewAt(0), GetSelectedView()); 252 SimulateMouseExitItemAt(0); 253 EXPECT_EQ(nil, GetSelectedView()); 254 255 // AppKit doesn't guarantee the order, so test moving between items. 256 SimulateMouseEnterItemAt(0); 257 EXPECT_EQ(GetItemViewAt(0), GetSelectedView()); 258 SimulateMouseEnterItemAt(1); 259 EXPECT_EQ(GetItemViewAt(1), GetSelectedView()); 260 SimulateMouseExitItemAt(0); 261 EXPECT_EQ(GetItemViewAt(1), GetSelectedView()); 262 SimulateMouseExitItemAt(1); 263 EXPECT_EQ(nil, GetSelectedView()); 264} 265 266// Test AppsGridPaginationObserver totalPagesChanged(). 267TEST_F(AppsGridControllerTest, PaginationObserverPagesChanged) { 268 scoped_nsobject<TestPaginationObserver> observer( 269 [[TestPaginationObserver alloc] init]); 270 [apps_grid_controller_ setPaginationObserver:observer]; 271 272 // Test totalPagesChanged. 273 model()->PopulateApps(kItemsPerPage); 274 EXPECT_EQ(0, [observer totalPagesChangedCount]); 275 EXPECT_EQ(1u, [apps_grid_controller_ pageCount]); 276 model()->PopulateApps(1); 277 EXPECT_EQ(1, [observer totalPagesChangedCount]); 278 EXPECT_EQ(2u, [apps_grid_controller_ pageCount]); 279 ReplaceTestModel(0); 280 EXPECT_EQ(2, [observer totalPagesChangedCount]); 281 EXPECT_EQ(1u, [apps_grid_controller_ pageCount]); 282 ReplaceTestModel(kItemsPerPage * 3 + 1); 283 EXPECT_EQ(3, [observer totalPagesChangedCount]); 284 EXPECT_EQ(4u, [apps_grid_controller_ pageCount]); 285 286 EXPECT_EQ(0, [observer selectedPageChangedCount]); 287 288 [apps_grid_controller_ setPaginationObserver:nil]; 289} 290 291// Test AppsGridPaginationObserver selectedPageChanged(). 292TEST_F(AppsGridControllerTest, PaginationObserverSelectedPageChanged) { 293 [AppsGridController setScrollAnimationDuration:0.0]; 294 scoped_nsobject<TestPaginationObserver> observer( 295 [[TestPaginationObserver alloc] init]); 296 [apps_grid_controller_ setPaginationObserver:observer]; 297 EXPECT_EQ(0, [[NSAnimationContext currentContext] duration]); 298 299 ReplaceTestModel(kItemsPerPage * 3 + 1); 300 EXPECT_EQ(1, [observer totalPagesChangedCount]); 301 EXPECT_EQ(4u, [apps_grid_controller_ pageCount]); 302 303 EXPECT_EQ(0, [observer selectedPageChangedCount]); 304 305 [apps_grid_controller_ scrollToPage:1]; 306 EXPECT_EQ(1, [observer selectedPageChangedCount]); 307 EXPECT_EQ(1, [observer lastNewSelectedPage]); 308 309 [apps_grid_controller_ scrollToPage:0]; 310 EXPECT_EQ(2, [observer selectedPageChangedCount]); 311 EXPECT_EQ(0, [observer lastNewSelectedPage]); 312 313 [apps_grid_controller_ scrollToPage:3]; 314 // Note: with no animations, there is only a single page change. However, with 315 // animations we expect multiple updates depending on the rate that the scroll 316 // view updates and sends out NSViewBoundsDidChangeNotification. 317 EXPECT_EQ(3, [observer selectedPageChangedCount]); 318 EXPECT_EQ(3, [observer lastNewSelectedPage]); 319 320 [apps_grid_controller_ setPaginationObserver:nil]; 321} 322 323namespace { 324 325// Generate a mouse event at the centre of the view in |page| with the given 326// |index_in_page| that can be used to initiate, update and complete drag 327// operations. 328NSEvent* MouseEventInCell(NSCollectionView* page, size_t index_in_page) { 329 NSRect cell_rect = [page frameForItemAtIndex:index_in_page]; 330 NSPoint point_in_view = NSMakePoint(NSMidX(cell_rect), NSMidY(cell_rect)); 331 NSPoint point_in_window = [page convertPoint:point_in_view 332 toView:nil]; 333 return cocoa_test_event_utils::LeftMouseDownAtPoint(point_in_window); 334} 335 336} // namespace 337 338// Test basic item moves with two items; swapping them around, dragging outside 339// of the view bounds, and dragging on the background. 340TEST_F(AppsGridControllerTest, DragAndDropSimple) { 341 model()->PopulateApps(2); 342 NSCollectionView* page = [apps_grid_controller_ collectionViewAtPageIndex:0]; 343 NSEvent* mouse_at_cell_0 = MouseEventInCell(page, 0); 344 NSEvent* mouse_at_cell_1 = MouseEventInCell(page, 1); 345 NSEvent* mouse_at_page_centre = MouseEventInCell(page, 6); 346 NSEvent* mouse_off_page = MouseEventInCell(page, kItemsPerPage * 2); 347 348 const std::string kOrdered = "Item 0,Item 1"; 349 const std::string kSwapped = "Item 1,Item 0"; 350 const std::string kOrderedView = "|Item 0,Item 1|"; 351 const std::string kSwappedView = "|Item 1,Item 0|"; 352 353 EXPECT_EQ(kOrdered, model()->GetModelContent()); 354 EXPECT_EQ(kOrderedView, GetViewContent()); 355 AppsCollectionViewDragManager* drag_manager = 356 [apps_grid_controller_ dragManager]; 357 358 // Drag first item over the second item and release. 359 [drag_manager onMouseDownInPage:page 360 withEvent:mouse_at_cell_0]; 361 [drag_manager onMouseDragged:mouse_at_cell_1]; 362 EXPECT_EQ(kOrdered, model()->GetModelContent()); 363 EXPECT_EQ(kSwappedView, GetViewContent()); // View swaps first. 364 [drag_manager onMouseUp:mouse_at_cell_1]; 365 EXPECT_EQ(kSwapped, model()->GetModelContent()); 366 EXPECT_EQ(kSwappedView, GetViewContent()); 367 368 // Drag item back. 369 [drag_manager onMouseDownInPage:page 370 withEvent:mouse_at_cell_1]; 371 [drag_manager onMouseDragged:mouse_at_cell_0]; 372 EXPECT_EQ(kSwapped, model()->GetModelContent()); 373 EXPECT_EQ(kOrderedView, GetViewContent()); 374 [drag_manager onMouseUp:mouse_at_cell_0]; 375 EXPECT_EQ(kOrdered, model()->GetModelContent()); 376 EXPECT_EQ(kOrderedView, GetViewContent()); 377 378 // Drag first item to centre of view (should put in last place). 379 [drag_manager onMouseDownInPage:page 380 withEvent:mouse_at_cell_0]; 381 [drag_manager onMouseDragged:mouse_at_page_centre]; 382 EXPECT_EQ(kOrdered, model()->GetModelContent()); 383 EXPECT_EQ(kSwappedView, GetViewContent()); 384 [drag_manager onMouseUp:mouse_at_page_centre]; 385 EXPECT_EQ(kSwapped, model()->GetModelContent()); 386 EXPECT_EQ(kSwappedView, GetViewContent()); 387 388 // Drag item to centre again (should leave it in the last place). 389 [drag_manager onMouseDownInPage:page 390 withEvent:mouse_at_cell_1]; 391 [drag_manager onMouseDragged:mouse_at_page_centre]; 392 EXPECT_EQ(kSwapped, model()->GetModelContent()); 393 EXPECT_EQ(kSwappedView, GetViewContent()); 394 [drag_manager onMouseUp:mouse_at_page_centre]; 395 EXPECT_EQ(kSwapped, model()->GetModelContent()); 396 EXPECT_EQ(kSwappedView, GetViewContent()); 397 398 // Drag starting in the centre of the view, should do nothing. 399 [drag_manager onMouseDownInPage:page 400 withEvent:mouse_at_page_centre]; 401 [drag_manager onMouseDragged:mouse_at_cell_0]; 402 EXPECT_EQ(kSwapped, model()->GetModelContent()); 403 EXPECT_EQ(kSwappedView, GetViewContent()); 404 [drag_manager onMouseUp:mouse_at_cell_0]; 405 EXPECT_EQ(kSwapped, model()->GetModelContent()); 406 EXPECT_EQ(kSwappedView, GetViewContent()); 407 408 // Click off page. 409 [drag_manager onMouseDownInPage:page 410 withEvent:mouse_off_page]; 411 [drag_manager onMouseDragged:mouse_at_cell_0]; 412 EXPECT_EQ(kSwapped, model()->GetModelContent()); 413 EXPECT_EQ(kSwappedView, GetViewContent()); 414 [drag_manager onMouseUp:mouse_at_cell_0]; 415 EXPECT_EQ(kSwapped, model()->GetModelContent()); 416 EXPECT_EQ(kSwappedView, GetViewContent()); 417 418 // Drag to first over second item, then off page. 419 [drag_manager onMouseDownInPage:page 420 withEvent:mouse_at_cell_0]; 421 [drag_manager onMouseDragged:mouse_at_cell_1]; 422 EXPECT_EQ(kSwapped, model()->GetModelContent()); 423 EXPECT_EQ(kOrderedView, GetViewContent()); 424 [drag_manager onMouseDragged:mouse_off_page]; 425 EXPECT_EQ(kSwapped, model()->GetModelContent()); 426 EXPECT_EQ(kOrderedView, GetViewContent()); 427 [drag_manager onMouseUp:mouse_off_page]; 428 EXPECT_EQ(kOrdered, model()->GetModelContent()); 429 EXPECT_EQ(kOrderedView, GetViewContent()); 430 431 // Replace with an empty model, and ensure we do not break. 432 ReplaceTestModel(0); 433 EXPECT_EQ(std::string(), model()->GetModelContent()); 434 EXPECT_EQ(std::string("||"), GetViewContent()); 435 [drag_manager onMouseDownInPage:page 436 withEvent:mouse_at_cell_0]; 437 [drag_manager onMouseDragged:mouse_at_cell_1]; 438 [drag_manager onMouseUp:mouse_at_cell_1]; 439 EXPECT_EQ(std::string(), model()->GetModelContent()); 440 EXPECT_EQ(std::string("||"), GetViewContent()); 441} 442 443// Test item moves between pages. 444TEST_F(AppsGridControllerTest, DragAndDropMultiPage) { 445 [AppsGridController setScrollAnimationDuration:0.0]; 446 const size_t kPagesToTest = 3; 447 // Put one item on the last page to hit more edge cases. 448 ReplaceTestModel(kItemsPerPage * (kPagesToTest - 1) + 1); 449 NSCollectionView* page[kPagesToTest]; 450 for (size_t i = 0; i < kPagesToTest; ++i) 451 page[i] = [apps_grid_controller_ collectionViewAtPageIndex:i]; 452 453 const std::string kSecondItemMovedToSecondPage = 454 "|Item 0,Item 2,Item 3,Item 4,Item 5,Item 6,Item 7,Item 8," 455 "Item 9,Item 10,Item 11,Item 12,Item 13,Item 14,Item 15,Item 16|" 456 "|Item 17,Item 1,Item 18,Item 19,Item 20,Item 21,Item 22,Item 23," 457 "Item 24,Item 25,Item 26,Item 27,Item 28,Item 29,Item 30,Item 31|" 458 "|Item 32|"; 459 460 NSEvent* mouse_at_cell_0 = MouseEventInCell(page[0], 0); 461 NSEvent* mouse_at_cell_1 = MouseEventInCell(page[0], 1); 462 AppsCollectionViewDragManager* drag_manager = 463 [apps_grid_controller_ dragManager]; 464 [drag_manager onMouseDownInPage:page[0] 465 withEvent:mouse_at_cell_1]; 466 467 // Initiate dragging before changing pages. 468 [drag_manager onMouseDragged:mouse_at_cell_0]; 469 470 // Scroll to the second page. 471 [apps_grid_controller_ scrollToPage:1]; 472 [drag_manager onMouseDragged:mouse_at_cell_1]; 473 474 // Do one exhaustive check, and then spot-check corner cases. 475 EXPECT_EQ(kSecondItemMovedToSecondPage, GetViewContent()); 476 EXPECT_EQ(0u, GetPageIndexForItem(0)); 477 EXPECT_EQ(1u, GetPageIndexForItem(1)); 478 EXPECT_EQ(0u, GetPageIndexForItem(2)); 479 EXPECT_EQ(0u, GetPageIndexForItem(16)); 480 EXPECT_EQ(1u, GetPageIndexForItem(17)); 481 EXPECT_EQ(1u, GetPageIndexForItem(31)); 482 EXPECT_EQ(2u, GetPageIndexForItem(32)); 483 484 // Scroll to the third page and drag some more. 485 [apps_grid_controller_ scrollToPage:2]; 486 [drag_manager onMouseDragged:mouse_at_cell_1]; 487 EXPECT_EQ(2u, GetPageIndexForItem(1)); 488 EXPECT_EQ(1u, GetPageIndexForItem(31)); 489 EXPECT_EQ(1u, GetPageIndexForItem(32)); 490 491 // Scroll backwards. 492 [apps_grid_controller_ scrollToPage:1]; 493 [drag_manager onMouseDragged:mouse_at_cell_1]; 494 EXPECT_EQ(kSecondItemMovedToSecondPage, GetViewContent()); 495 EXPECT_EQ(1u, GetPageIndexForItem(1)); 496 EXPECT_EQ(1u, GetPageIndexForItem(31)); 497 EXPECT_EQ(2u, GetPageIndexForItem(32)); 498 499 // Simulate installing an item while dragging (or have it appear during sync). 500 model()->PopulateAppWithId(33); 501 // Item should go back to its position before the drag. 502 EXPECT_EQ(0u, GetPageIndexForItem(1)); 503 EXPECT_EQ(1u, GetPageIndexForItem(31)); 504 EXPECT_EQ(2u, GetPageIndexForItem(32)); 505 // New item should appear at end. 506 EXPECT_EQ(2u, GetPageIndexForItem(33)); 507 508 // Scroll to end again, and keep dragging (should be ignored). 509 [apps_grid_controller_ scrollToPage:2]; 510 [drag_manager onMouseDragged:mouse_at_cell_0]; 511 EXPECT_EQ(0u, GetPageIndexForItem(1)); 512 [drag_manager onMouseUp:mouse_at_cell_0]; 513 EXPECT_EQ(0u, GetPageIndexForItem(1)); 514} 515 516} // namespace test 517} // namespace app_list 518