Upstream version 6.35.121.0
[platform/framework/web/crosswalk.git] / src / ash / shelf / shelf_view_unittest.cc
1 // Copyright (c) 2012 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 "ash/shelf/shelf_view.h"
6
7 #include <algorithm>
8 #include <vector>
9
10 #include "ash/ash_switches.h"
11 #include "ash/root_window_controller.h"
12 #include "ash/shelf/overflow_bubble.h"
13 #include "ash/shelf/overflow_bubble_view.h"
14 #include "ash/shelf/shelf.h"
15 #include "ash/shelf/shelf_button.h"
16 #include "ash/shelf/shelf_constants.h"
17 #include "ash/shelf/shelf_icon_observer.h"
18 #include "ash/shelf/shelf_item_delegate_manager.h"
19 #include "ash/shelf/shelf_layout_manager.h"
20 #include "ash/shelf/shelf_model.h"
21 #include "ash/shelf/shelf_tooltip_manager.h"
22 #include "ash/shelf/shelf_widget.h"
23 #include "ash/shell.h"
24 #include "ash/shell_window_ids.h"
25 #include "ash/test/ash_test_base.h"
26 #include "ash/test/overflow_bubble_view_test_api.h"
27 #include "ash/test/shelf_test_api.h"
28 #include "ash/test/shelf_view_test_api.h"
29 #include "ash/test/shell_test_api.h"
30 #include "ash/test/test_shelf_delegate.h"
31 #include "ash/test/test_shelf_item_delegate.h"
32 #include "ash/wm/coordinate_conversion.h"
33 #include "base/basictypes.h"
34 #include "base/command_line.h"
35 #include "base/compiler_specific.h"
36 #include "base/memory/scoped_ptr.h"
37 #include "base/strings/string_number_conversions.h"
38 #include "grit/ash_resources.h"
39 #include "ui/aura/test/aura_test_base.h"
40 #include "ui/aura/test/event_generator.h"
41 #include "ui/aura/window.h"
42 #include "ui/aura/window_event_dispatcher.h"
43 #include "ui/base/l10n/l10n_util.h"
44 #include "ui/compositor/layer.h"
45 #include "ui/events/event.h"
46 #include "ui/events/event_constants.h"
47 #include "ui/views/view_model.h"
48 #include "ui/views/widget/widget.h"
49 #include "ui/views/widget/widget_delegate.h"
50
51 namespace ash {
52 namespace test {
53
54 ////////////////////////////////////////////////////////////////////////////////
55 // ShelfIconObserver tests.
56
57 class TestShelfIconObserver : public ShelfIconObserver {
58  public:
59   explicit TestShelfIconObserver(Shelf* shelf)
60       : shelf_(shelf),
61         change_notified_(false) {
62     if (shelf_)
63       shelf_->AddIconObserver(this);
64   }
65
66   virtual ~TestShelfIconObserver() {
67     if (shelf_)
68       shelf_->RemoveIconObserver(this);
69   }
70
71   // ShelfIconObserver implementation.
72   virtual void OnShelfIconPositionsChanged() OVERRIDE {
73     change_notified_ = true;
74   }
75
76   int change_notified() const { return change_notified_; }
77   void Reset() { change_notified_ = false; }
78
79  private:
80   Shelf* shelf_;
81   bool change_notified_;
82
83   DISALLOW_COPY_AND_ASSIGN(TestShelfIconObserver);
84 };
85
86 class ShelfViewIconObserverTest : public AshTestBase {
87  public:
88   ShelfViewIconObserverTest() {}
89   virtual ~ShelfViewIconObserverTest() {}
90
91   virtual void SetUp() OVERRIDE {
92     AshTestBase::SetUp();
93     Shelf* shelf = Shelf::ForPrimaryDisplay();
94     observer_.reset(new TestShelfIconObserver(shelf));
95
96     shelf_view_test_.reset(
97         new ShelfViewTestAPI(ShelfTestAPI(shelf).shelf_view()));
98     shelf_view_test_->SetAnimationDuration(1);
99   }
100
101   virtual void TearDown() OVERRIDE {
102     observer_.reset();
103     AshTestBase::TearDown();
104   }
105
106   TestShelfIconObserver* observer() { return observer_.get(); }
107
108   ShelfViewTestAPI* shelf_view_test() {
109     return shelf_view_test_.get();
110   }
111
112   Shelf* ShelfForSecondaryDisplay() {
113     return Shelf::ForWindow(Shell::GetAllRootWindows()[1]);
114   }
115
116  private:
117   scoped_ptr<TestShelfIconObserver> observer_;
118   scoped_ptr<ShelfViewTestAPI> shelf_view_test_;
119
120   DISALLOW_COPY_AND_ASSIGN(ShelfViewIconObserverTest);
121 };
122
123 TEST_F(ShelfViewIconObserverTest, AddRemove) {
124   TestShelfDelegate* shelf_delegate = TestShelfDelegate::instance();
125   ASSERT_TRUE(shelf_delegate);
126
127   views::Widget::InitParams params(views::Widget::InitParams::TYPE_WINDOW);
128   params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
129   params.bounds = gfx::Rect(0, 0, 200, 200);
130   params.context = CurrentContext();
131
132   scoped_ptr<views::Widget> widget(new views::Widget());
133   widget->Init(params);
134   shelf_delegate->AddShelfItem(widget->GetNativeWindow());
135   shelf_view_test()->RunMessageLoopUntilAnimationsDone();
136   EXPECT_TRUE(observer()->change_notified());
137   observer()->Reset();
138
139   widget->Show();
140   widget->GetNativeWindow()->parent()->RemoveChild(widget->GetNativeWindow());
141   shelf_view_test()->RunMessageLoopUntilAnimationsDone();
142   EXPECT_TRUE(observer()->change_notified());
143   observer()->Reset();
144 }
145
146 // Sometimes fails on trybots on win7_aura. http://crbug.com/177135
147 #if defined(OS_WIN)
148 #define MAYBE_AddRemoveWithMultipleDisplays \
149     DISABLED_AddRemoveWithMultipleDisplays
150 #else
151 #define MAYBE_AddRemoveWithMultipleDisplays \
152     AddRemoveWithMultipleDisplays
153 #endif
154 // Make sure creating/deleting an window on one displays notifies a
155 // shelf on external display as well as one on primary.
156 TEST_F(ShelfViewIconObserverTest, MAYBE_AddRemoveWithMultipleDisplays) {
157   UpdateDisplay("400x400,400x400");
158   TestShelfIconObserver second_observer(ShelfForSecondaryDisplay());
159
160   TestShelfDelegate* shelf_delegate = TestShelfDelegate::instance();
161   ASSERT_TRUE(shelf_delegate);
162
163   views::Widget::InitParams params(views::Widget::InitParams::TYPE_WINDOW);
164   params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
165   params.bounds = gfx::Rect(0, 0, 200, 200);
166   params.context = CurrentContext();
167
168   scoped_ptr<views::Widget> widget(new views::Widget());
169   widget->Init(params);
170   shelf_delegate->AddShelfItem(widget->GetNativeWindow());
171   shelf_view_test()->RunMessageLoopUntilAnimationsDone();
172   EXPECT_TRUE(observer()->change_notified());
173   EXPECT_TRUE(second_observer.change_notified());
174   observer()->Reset();
175   second_observer.Reset();
176
177   widget->GetNativeWindow()->parent()->RemoveChild(widget->GetNativeWindow());
178   shelf_view_test()->RunMessageLoopUntilAnimationsDone();
179   EXPECT_TRUE(observer()->change_notified());
180   EXPECT_TRUE(second_observer.change_notified());
181
182   observer()->Reset();
183   second_observer.Reset();
184 }
185
186 TEST_F(ShelfViewIconObserverTest, BoundsChanged) {
187   ShelfWidget* widget = Shell::GetPrimaryRootWindowController()->shelf();
188   Shelf* shelf = Shelf::ForPrimaryDisplay();
189   gfx::Size shelf_size = widget->GetWindowBoundsInScreen().size();
190   shelf_size.set_width(shelf_size.width() / 2);
191   ASSERT_GT(shelf_size.width(), 0);
192   shelf->SetShelfViewBounds(gfx::Rect(shelf_size));
193   // No animation happens for ShelfView bounds change.
194   EXPECT_TRUE(observer()->change_notified());
195   observer()->Reset();
196 }
197
198 ////////////////////////////////////////////////////////////////////////////////
199 // ShelfView tests.
200
201 // Simple ShelfDelegate implmentation for ShelfViewTest.OverflowBubbleSize
202 // and CheckDragAndDropFromOverflowBubbleToShelf
203 class TestShelfDelegateForShelfView : public ShelfDelegate {
204  public:
205   explicit TestShelfDelegateForShelfView(ShelfModel* model)
206       : model_(model) {}
207   virtual ~TestShelfDelegateForShelfView() {}
208
209   // ShelfDelegate overrides:
210   virtual void OnShelfCreated(Shelf* shelf) OVERRIDE {}
211
212   virtual void OnShelfDestroyed(Shelf* shelf) OVERRIDE {}
213
214   virtual ShelfID GetShelfIDForAppID(const std::string& app_id) OVERRIDE {
215     ShelfID id = 0;
216     EXPECT_TRUE(base::StringToInt(app_id, &id));
217     return id;
218   }
219
220   virtual const std::string& GetAppIDForShelfID(ShelfID id) OVERRIDE {
221     // Use |app_id_| member variable because returning a reference to local
222     // variable is not allowed.
223     app_id_ = base::IntToString(id);
224     return app_id_;
225   }
226
227   virtual void PinAppWithID(const std::string& app_id) OVERRIDE {
228   }
229
230   virtual bool IsAppPinned(const std::string& app_id) OVERRIDE {
231     // Returns true for ShelfViewTest.OverflowBubbleSize. To test ripping off in
232     // that test, an item is already pinned state.
233     return true;
234   }
235
236   virtual bool CanPin() const OVERRIDE {
237     return true;
238   }
239
240   virtual void UnpinAppWithID(const std::string& app_id) OVERRIDE {
241     ShelfID id = 0;
242     EXPECT_TRUE(base::StringToInt(app_id, &id));
243     ASSERT_GT(id, 0);
244     int index = model_->ItemIndexByID(id);
245     ASSERT_GE(index, 0);
246
247     model_->RemoveItemAt(index);
248   }
249
250  private:
251   ShelfModel* model_;
252
253   // Temp member variable for returning a value. See the comment in the
254   // GetAppIDForShelfID().
255   std::string app_id_;
256
257   DISALLOW_COPY_AND_ASSIGN(TestShelfDelegateForShelfView);
258 };
259
260 class ShelfViewTest : public AshTestBase {
261  public:
262   ShelfViewTest() : model_(NULL), shelf_view_(NULL), browser_index_(1) {}
263   virtual ~ShelfViewTest() {}
264
265   virtual void SetUp() OVERRIDE {
266     AshTestBase::SetUp();
267     test::ShellTestApi test_api(Shell::GetInstance());
268     model_ = test_api.shelf_model();
269     Shelf* shelf = Shelf::ForPrimaryDisplay();
270     shelf_view_ = ShelfTestAPI(shelf).shelf_view();
271
272     // The bounds should be big enough for 4 buttons + overflow chevron.
273     shelf_view_->SetBounds(0, 0, 500,
274         internal::ShelfLayoutManager::GetPreferredShelfSize());
275
276     test_api_.reset(new ShelfViewTestAPI(shelf_view_));
277     test_api_->SetAnimationDuration(1);  // Speeds up animation for test.
278
279     item_manager_ = Shell::GetInstance()->shelf_item_delegate_manager();
280     DCHECK(item_manager_);
281
282     // Add browser shortcut shelf item at index 0 for test.
283     AddBrowserShortcut();
284   }
285
286   virtual void TearDown() OVERRIDE {
287     test_api_.reset();
288     AshTestBase::TearDown();
289   }
290
291  protected:
292   void CreateAndSetShelfItemDelegateForID(ShelfID id) {
293     scoped_ptr<ShelfItemDelegate> delegate(new TestShelfItemDelegate(NULL));
294     item_manager_->SetShelfItemDelegate(id, delegate.Pass());
295   }
296
297   ShelfID AddBrowserShortcut() {
298     ShelfItem browser_shortcut;
299     browser_shortcut.type = TYPE_BROWSER_SHORTCUT;
300
301     ShelfID id = model_->next_id();
302     model_->AddAt(browser_index_, browser_shortcut);
303     CreateAndSetShelfItemDelegateForID(id);
304     test_api_->RunMessageLoopUntilAnimationsDone();
305     return id;
306   }
307
308   ShelfID AddAppShortcut() {
309     ShelfItem item;
310     item.type = TYPE_APP_SHORTCUT;
311     item.status = STATUS_CLOSED;
312
313     ShelfID id = model_->next_id();
314     model_->Add(item);
315     CreateAndSetShelfItemDelegateForID(id);
316     test_api_->RunMessageLoopUntilAnimationsDone();
317     return id;
318   }
319
320   ShelfID AddPanel() {
321     ShelfID id = AddPanelNoWait();
322     test_api_->RunMessageLoopUntilAnimationsDone();
323     return id;
324   }
325
326   ShelfID AddPlatformAppNoWait() {
327     ShelfItem item;
328     item.type = TYPE_PLATFORM_APP;
329     item.status = STATUS_RUNNING;
330
331     ShelfID id = model_->next_id();
332     model_->Add(item);
333     CreateAndSetShelfItemDelegateForID(id);
334     return id;
335   }
336
337   ShelfID AddPanelNoWait() {
338     ShelfItem item;
339     item.type = TYPE_APP_PANEL;
340     item.status = STATUS_RUNNING;
341
342     ShelfID id = model_->next_id();
343     model_->Add(item);
344     CreateAndSetShelfItemDelegateForID(id);
345     return id;
346   }
347
348   ShelfID AddPlatformApp() {
349     ShelfID id = AddPlatformAppNoWait();
350     test_api_->RunMessageLoopUntilAnimationsDone();
351     return id;
352   }
353
354   void RemoveByID(ShelfID id) {
355     model_->RemoveItemAt(model_->ItemIndexByID(id));
356     test_api_->RunMessageLoopUntilAnimationsDone();
357   }
358
359   internal::ShelfButton* GetButtonByID(ShelfID id) {
360     int index = model_->ItemIndexByID(id);
361     return test_api_->GetButton(index);
362   }
363
364   ShelfItem GetItemByID(ShelfID id) {
365     ShelfItems::const_iterator items = model_->ItemByID(id);
366     return *items;
367   }
368
369   void CheckModelIDs(
370       const std::vector<std::pair<ShelfID, views::View*> >& id_map) {
371     size_t map_index = 0;
372     for (size_t model_index = 0;
373          model_index < model_->items().size();
374          ++model_index) {
375       ShelfItem item = model_->items()[model_index];
376       ShelfID id = item.id;
377       EXPECT_EQ(id_map[map_index].first, id);
378       EXPECT_EQ(id_map[map_index].second, GetButtonByID(id));
379       ++map_index;
380     }
381     ASSERT_EQ(map_index, id_map.size());
382   }
383
384   void VerifyShelfItemBoundsAreValid() {
385     for (int i=0;i <= test_api_->GetLastVisibleIndex(); ++i) {
386       if (test_api_->GetButton(i)) {
387         gfx::Rect shelf_view_bounds = shelf_view_->GetLocalBounds();
388         gfx::Rect item_bounds = test_api_->GetBoundsByIndex(i);
389         EXPECT_GE(item_bounds.x(), 0);
390         EXPECT_GE(item_bounds.y(), 0);
391         EXPECT_LE(item_bounds.right(), shelf_view_bounds.width());
392         EXPECT_LE(item_bounds.bottom(), shelf_view_bounds.height());
393       }
394     }
395   }
396
397   views::View* SimulateButtonPressed(
398       internal::ShelfButtonHost::Pointer pointer,
399       int button_index) {
400     internal::ShelfButtonHost* button_host = shelf_view_;
401     views::View* button = test_api_->GetButton(button_index);
402     ui::MouseEvent click_event(ui::ET_MOUSE_PRESSED,
403                                button->bounds().origin(),
404                                button->GetBoundsInScreen().origin(), 0, 0);
405     button_host->PointerPressedOnButton(button, pointer, click_event);
406     return button;
407   }
408
409   views::View* SimulateClick(internal::ShelfButtonHost::Pointer pointer,
410                              int button_index) {
411     internal::ShelfButtonHost* button_host = shelf_view_;
412     views::View* button = SimulateButtonPressed(pointer, button_index);
413     button_host->PointerReleasedOnButton(button,
414                                          internal::ShelfButtonHost::MOUSE,
415                                          false);
416     return button;
417   }
418
419   views::View* SimulateDrag(internal::ShelfButtonHost::Pointer pointer,
420                             int button_index,
421                             int destination_index) {
422     internal::ShelfButtonHost* button_host = shelf_view_;
423     views::View* button = SimulateButtonPressed(pointer, button_index);
424
425     // Drag.
426     views::View* destination = test_api_->GetButton(destination_index);
427     ui::MouseEvent drag_event(ui::ET_MOUSE_DRAGGED,
428                               destination->bounds().origin(),
429                               destination->GetBoundsInScreen().origin(), 0, 0);
430     button_host->PointerDraggedOnButton(button, pointer, drag_event);
431     return button;
432   }
433
434   void SetupForDragTest(
435       std::vector<std::pair<ShelfID, views::View*> >* id_map) {
436     // Initialize |id_map| with the automatically-created shelf buttons.
437     for (size_t i = 0; i < model_->items().size(); ++i) {
438       internal::ShelfButton* button = test_api_->GetButton(i);
439       id_map->push_back(std::make_pair(model_->items()[i].id, button));
440     }
441     ASSERT_NO_FATAL_FAILURE(CheckModelIDs(*id_map));
442
443     // Add 5 app shelf buttons for testing.
444     for (int i = 0; i < 5; ++i) {
445       ShelfID id = AddAppShortcut();
446       // App Icon is located at index 0, and browser shortcut is located at
447       // index 1. So we should start to add app shortcut at index 2.
448       id_map->insert(id_map->begin() + (i + browser_index_ + 1),
449                      std::make_pair(id, GetButtonByID(id)));
450     }
451     ASSERT_NO_FATAL_FAILURE(CheckModelIDs(*id_map));
452   }
453
454   views::View* GetTooltipAnchorView() {
455     return shelf_view_->tooltip_manager()->anchor_;
456   }
457
458   void AddButtonsUntilOverflow() {
459     int items_added = 0;
460     while (!test_api_->IsOverflowButtonVisible()) {
461       AddAppShortcut();
462       ++items_added;
463       ASSERT_LT(items_added, 10000);
464     }
465   }
466
467   void ShowTooltip() {
468     shelf_view_->tooltip_manager()->ShowInternal();
469   }
470
471   void TestDraggingAnItemFromOverflowToShelf(bool cancel) {
472     test_api_->ShowOverflowBubble();
473     ASSERT_TRUE(test_api_->overflow_bubble() &&
474                 test_api_->overflow_bubble()->IsShowing());
475
476     ash::test::ShelfViewTestAPI test_api_for_overflow(
477       test_api_->overflow_bubble()->shelf_view());
478
479     int total_item_count = model_->item_count();
480
481     int last_visible_item_id_in_shelf =
482         GetItemId(test_api_->GetLastVisibleIndex());
483     int second_last_visible_item_id_in_shelf =
484         GetItemId(test_api_->GetLastVisibleIndex() - 1);
485     int first_visible_item_id_in_overflow =
486         GetItemId(test_api_for_overflow.GetFirstVisibleIndex());
487     int second_last_visible_item_id_in_overflow =
488         GetItemId(test_api_for_overflow.GetLastVisibleIndex() - 1);
489
490     int drag_item_index =
491         test_api_for_overflow.GetLastVisibleIndex();
492     ShelfID drag_item_id = GetItemId(drag_item_index);
493     internal::ShelfButton* drag_button =
494         test_api_for_overflow.GetButton(drag_item_index);
495     gfx::Point center_point_of_drag_item =
496         drag_button->GetBoundsInScreen().CenterPoint();
497
498     aura::test::EventGenerator generator(ash::Shell::GetPrimaryRootWindow(),
499                                          center_point_of_drag_item);
500     // Rip an item off to OverflowBubble.
501     generator.PressLeftButton();
502     gfx::Point rip_off_point(center_point_of_drag_item.x(), 0);
503     generator.MoveMouseTo(rip_off_point);
504     test_api_for_overflow.RunMessageLoopUntilAnimationsDone();
505     ASSERT_TRUE(test_api_for_overflow.IsRippedOffFromShelf());
506     ASSERT_FALSE(test_api_for_overflow.DraggedItemFromOverflowToShelf());
507
508     // Move a dragged item into Shelf at |drop_index|.
509     int drop_index = 1;
510     gfx::Point drop_point =
511         test_api_->GetButton(drop_index)->GetBoundsInScreen().CenterPoint();
512     int item_width = test_api_for_overflow.GetButtonSize();
513     // To insert at |drop_index|, more smaller x-axis value of |drop_point|
514     // should be used.
515     gfx::Point modified_drop_point(drop_point.x() - item_width / 4,
516                                    drop_point.y());
517     generator.MoveMouseTo(modified_drop_point);
518     test_api_for_overflow.RunMessageLoopUntilAnimationsDone();
519     test_api_->RunMessageLoopUntilAnimationsDone();
520     ASSERT_TRUE(test_api_for_overflow.IsRippedOffFromShelf());
521     ASSERT_TRUE(test_api_for_overflow.DraggedItemFromOverflowToShelf());
522
523     if (cancel)
524       drag_button->OnMouseCaptureLost();
525     else
526       generator.ReleaseLeftButton();
527
528     test_api_for_overflow.RunMessageLoopUntilAnimationsDone();
529     test_api_->RunMessageLoopUntilAnimationsDone();
530     ASSERT_FALSE(test_api_for_overflow.IsRippedOffFromShelf());
531     ASSERT_FALSE(test_api_for_overflow.DraggedItemFromOverflowToShelf());
532
533     // Compare pre-stored items' id with newly positioned items' after dragging
534     // is canceled or finished.
535     if (cancel) {
536       EXPECT_EQ(last_visible_item_id_in_shelf,
537                 GetItemId(test_api_->GetLastVisibleIndex()));
538       EXPECT_EQ(second_last_visible_item_id_in_shelf,
539                 GetItemId(test_api_->GetLastVisibleIndex() - 1));
540       EXPECT_EQ(first_visible_item_id_in_overflow,
541                 GetItemId(test_api_for_overflow.GetFirstVisibleIndex()));
542       EXPECT_EQ(second_last_visible_item_id_in_overflow,
543                 GetItemId(test_api_for_overflow.GetLastVisibleIndex() - 1));
544     } else {
545       EXPECT_EQ(drag_item_id, GetItemId(drop_index));
546       EXPECT_EQ(total_item_count, model_->item_count());
547       EXPECT_EQ(last_visible_item_id_in_shelf,
548                 GetItemId(test_api_for_overflow.GetFirstVisibleIndex()));
549       EXPECT_EQ(second_last_visible_item_id_in_shelf,
550                 GetItemId(test_api_->GetLastVisibleIndex()));
551       EXPECT_EQ(first_visible_item_id_in_overflow,
552                 GetItemId(test_api_for_overflow.GetFirstVisibleIndex() + 1));
553       EXPECT_EQ(second_last_visible_item_id_in_overflow,
554                 GetItemId(test_api_for_overflow.GetLastVisibleIndex()));
555     }
556   }
557
558   // Returns the item's ShelfID at |index|.
559   ShelfID GetItemId(int index) {
560     DCHECK_GE(index, 0);
561     return model_->items()[index].id;
562   }
563
564   void ReplaceShelfDelegateForRipOffTest() {
565     // Replace ShelfDelegate.
566     test::ShellTestApi test_api(Shell::GetInstance());
567     test_api.SetShelfDelegate(NULL);
568     ShelfDelegate* delegate = new TestShelfDelegateForShelfView(model_);
569     test_api.SetShelfDelegate(delegate);
570     test::ShelfTestAPI(Shelf::ForPrimaryDisplay()).SetShelfDelegate(delegate);
571     test_api_->SetShelfDelegate(delegate);
572   }
573
574   ShelfModel* model_;
575   internal::ShelfView* shelf_view_;
576   int browser_index_;
577   ShelfItemDelegateManager* item_manager_;
578
579   scoped_ptr<ShelfViewTestAPI> test_api_;
580
581  private:
582   DISALLOW_COPY_AND_ASSIGN(ShelfViewTest);
583 };
584
585 class ShelfViewLegacyShelfLayoutTest : public ShelfViewTest {
586  public:
587   ShelfViewLegacyShelfLayoutTest() : ShelfViewTest() {
588     browser_index_ = 0;
589   }
590
591   virtual ~ShelfViewLegacyShelfLayoutTest() {}
592
593   virtual void SetUp() OVERRIDE {
594     CommandLine::ForCurrentProcess()->AppendSwitch(
595         ash::switches::kAshDisableAlternateShelfLayout);
596     ShelfViewTest::SetUp();
597   }
598
599  private:
600   DISALLOW_COPY_AND_ASSIGN(ShelfViewLegacyShelfLayoutTest);
601 };
602
603 class ScopedTextDirectionChange {
604  public:
605   ScopedTextDirectionChange(bool is_rtl)
606       : is_rtl_(is_rtl) {
607     original_locale_ = l10n_util::GetApplicationLocale(std::string());
608     if (is_rtl_)
609       base::i18n::SetICUDefaultLocale("he");
610     CheckTextDirectionIsCorrect();
611   }
612
613   ~ScopedTextDirectionChange() {
614     if (is_rtl_)
615       base::i18n::SetICUDefaultLocale(original_locale_);
616   }
617
618  private:
619   void CheckTextDirectionIsCorrect() {
620     ASSERT_EQ(is_rtl_, base::i18n::IsRTL());
621   }
622
623   bool is_rtl_;
624   std::string original_locale_;
625 };
626
627 class ShelfViewTextDirectionTest
628     : public ShelfViewTest,
629       public testing::WithParamInterface<bool> {
630  public:
631   ShelfViewTextDirectionTest() : text_direction_change_(GetParam()) {}
632   virtual ~ShelfViewTextDirectionTest() {}
633
634   virtual void SetUp() OVERRIDE {
635     ShelfViewTest::SetUp();
636   }
637
638   virtual void TearDown() OVERRIDE {
639     ShelfViewTest::TearDown();
640   }
641
642  private:
643   ScopedTextDirectionChange text_direction_change_;
644
645   DISALLOW_COPY_AND_ASSIGN(ShelfViewTextDirectionTest);
646 };
647
648 // Checks that the ideal item icon bounds match the view's bounds in the screen
649 // in both LTR and RTL.
650 TEST_P(ShelfViewTextDirectionTest, IdealBoundsOfItemIcon) {
651   ShelfID id = AddPlatformApp();
652   internal::ShelfButton* button = GetButtonByID(id);
653   gfx::Rect item_bounds = button->GetBoundsInScreen();
654   gfx::Point icon_offset = button->GetIconBounds().origin();
655   item_bounds.Offset(icon_offset.OffsetFromOrigin());
656   gfx::Rect ideal_bounds = shelf_view_->GetIdealBoundsOfItemIcon(id);
657   gfx::Point screen_origin;
658   views::View::ConvertPointToScreen(shelf_view_, &screen_origin);
659   ideal_bounds.Offset(screen_origin.x(), screen_origin.y());
660   EXPECT_EQ(item_bounds.x(), ideal_bounds.x());
661   EXPECT_EQ(item_bounds.y(), ideal_bounds.y());
662 }
663
664 // Checks that shelf view contents are considered in the correct drag group.
665 TEST_F(ShelfViewTest, EnforceDragType) {
666   EXPECT_TRUE(test_api_->SameDragType(TYPE_PLATFORM_APP, TYPE_PLATFORM_APP));
667   EXPECT_FALSE(test_api_->SameDragType(TYPE_PLATFORM_APP, TYPE_APP_SHORTCUT));
668   EXPECT_FALSE(test_api_->SameDragType(TYPE_PLATFORM_APP,
669                                        TYPE_BROWSER_SHORTCUT));
670   EXPECT_FALSE(test_api_->SameDragType(TYPE_PLATFORM_APP, TYPE_WINDOWED_APP));
671   EXPECT_FALSE(test_api_->SameDragType(TYPE_PLATFORM_APP, TYPE_APP_LIST));
672   EXPECT_FALSE(test_api_->SameDragType(TYPE_PLATFORM_APP, TYPE_APP_PANEL));
673
674   EXPECT_TRUE(test_api_->SameDragType(TYPE_APP_SHORTCUT, TYPE_APP_SHORTCUT));
675   EXPECT_TRUE(test_api_->SameDragType(TYPE_APP_SHORTCUT,
676                                       TYPE_BROWSER_SHORTCUT));
677   EXPECT_FALSE(test_api_->SameDragType(TYPE_APP_SHORTCUT,
678                                        TYPE_WINDOWED_APP));
679   EXPECT_FALSE(test_api_->SameDragType(TYPE_APP_SHORTCUT, TYPE_APP_LIST));
680   EXPECT_FALSE(test_api_->SameDragType(TYPE_APP_SHORTCUT, TYPE_APP_PANEL));
681
682   EXPECT_TRUE(test_api_->SameDragType(TYPE_BROWSER_SHORTCUT,
683                                       TYPE_BROWSER_SHORTCUT));
684   EXPECT_FALSE(test_api_->SameDragType(TYPE_BROWSER_SHORTCUT,
685                                        TYPE_WINDOWED_APP));
686   EXPECT_FALSE(test_api_->SameDragType(TYPE_BROWSER_SHORTCUT, TYPE_APP_LIST));
687   EXPECT_FALSE(test_api_->SameDragType(TYPE_BROWSER_SHORTCUT, TYPE_APP_PANEL));
688
689   EXPECT_TRUE(test_api_->SameDragType(TYPE_WINDOWED_APP, TYPE_WINDOWED_APP));
690   EXPECT_FALSE(test_api_->SameDragType(TYPE_WINDOWED_APP, TYPE_APP_LIST));
691   EXPECT_FALSE(test_api_->SameDragType(TYPE_WINDOWED_APP, TYPE_APP_PANEL));
692
693   EXPECT_TRUE(test_api_->SameDragType(TYPE_APP_LIST, TYPE_APP_LIST));
694   EXPECT_FALSE(test_api_->SameDragType(TYPE_APP_LIST, TYPE_APP_PANEL));
695
696   EXPECT_TRUE(test_api_->SameDragType(TYPE_APP_PANEL, TYPE_APP_PANEL));
697 }
698
699 // Adds platform app button until overflow and verifies that the last added
700 // platform app button is hidden.
701 TEST_F(ShelfViewTest, AddBrowserUntilOverflow) {
702   // All buttons should be visible.
703   ASSERT_EQ(test_api_->GetButtonCount(),
704             test_api_->GetLastVisibleIndex() + 1);
705
706   // Add platform app button until overflow.
707   int items_added = 0;
708   ShelfID last_added = AddPlatformApp();
709   while (!test_api_->IsOverflowButtonVisible()) {
710     // Added button is visible after animation while in this loop.
711     EXPECT_TRUE(GetButtonByID(last_added)->visible());
712
713     last_added = AddPlatformApp();
714     ++items_added;
715     ASSERT_LT(items_added, 10000);
716   }
717
718   // The last added button should be invisible.
719   EXPECT_FALSE(GetButtonByID(last_added)->visible());
720 }
721
722 // Adds one platform app button then adds app shortcut until overflow. Verifies
723 // that the browser button gets hidden on overflow and last added app shortcut
724 // is still visible.
725 TEST_F(ShelfViewTest, AddAppShortcutWithBrowserButtonUntilOverflow) {
726   // All buttons should be visible.
727   ASSERT_EQ(test_api_->GetButtonCount(),
728             test_api_->GetLastVisibleIndex() + 1);
729
730   ShelfID browser_button_id = AddPlatformApp();
731
732   // Add app shortcut until overflow.
733   int items_added = 0;
734   ShelfID last_added = AddAppShortcut();
735   while (!test_api_->IsOverflowButtonVisible()) {
736     // Added button is visible after animation while in this loop.
737     EXPECT_TRUE(GetButtonByID(last_added)->visible());
738
739     last_added = AddAppShortcut();
740     ++items_added;
741     ASSERT_LT(items_added, 10000);
742   }
743
744   // And the platform app button is invisible.
745   EXPECT_FALSE(GetButtonByID(browser_button_id)->visible());
746 }
747
748 TEST_F(ShelfViewLegacyShelfLayoutTest,
749        AddAppShortcutWithBrowserButtonUntilOverflow) {
750   // All buttons should be visible.
751   ASSERT_EQ(test_api_->GetButtonCount(),
752             test_api_->GetLastVisibleIndex() + 1);
753
754
755   ShelfID browser_button_id = AddPlatformApp();
756
757   // Add app shortcut until overflow.
758   int items_added = 0;
759   ShelfID last_added = AddAppShortcut();
760   while (!test_api_->IsOverflowButtonVisible()) {
761     // Added button is visible after animation while in this loop.
762     EXPECT_TRUE(GetButtonByID(last_added)->visible());
763
764     last_added = AddAppShortcut();
765     ++items_added;
766     ASSERT_LT(items_added, 10000);
767   }
768
769   // The last added app short button should be visible.
770   EXPECT_TRUE(GetButtonByID(last_added)->visible());
771   // And the platform app button is invisible.
772   EXPECT_FALSE(GetButtonByID(browser_button_id)->visible());
773 }
774
775 TEST_F(ShelfViewTest, AddPanelHidesPlatformAppButton) {
776   // All buttons should be visible.
777   ASSERT_EQ(test_api_->GetButtonCount(),
778             test_api_->GetLastVisibleIndex() + 1);
779
780   // Add platform app button until overflow, remember last visible platform app
781   // button.
782   int items_added = 0;
783   ShelfID first_added = AddPlatformApp();
784   EXPECT_TRUE(GetButtonByID(first_added)->visible());
785   while (true) {
786     ShelfID added = AddPlatformApp();
787     if (test_api_->IsOverflowButtonVisible()) {
788       EXPECT_FALSE(GetButtonByID(added)->visible());
789       RemoveByID(added);
790       break;
791     }
792     ++items_added;
793     ASSERT_LT(items_added, 10000);
794   }
795
796   ShelfID panel = AddPanel();
797   EXPECT_TRUE(test_api_->IsOverflowButtonVisible());
798
799   RemoveByID(panel);
800   EXPECT_FALSE(test_api_->IsOverflowButtonVisible());
801 }
802
803 TEST_F(ShelfViewLegacyShelfLayoutTest, AddPanelHidesPlatformAppButton) {
804   // All buttons should be visible.
805   ASSERT_EQ(test_api_->GetButtonCount(),
806             test_api_->GetLastVisibleIndex() + 1);
807
808   // Add platform app button until overflow, remember last visible platform app
809   // button.
810   int items_added = 0;
811   ShelfID first_added = AddPlatformApp();
812   EXPECT_TRUE(GetButtonByID(first_added)->visible());
813   ShelfID last_visible = first_added;
814   while (true) {
815     ShelfID added = AddPlatformApp();
816     if (test_api_->IsOverflowButtonVisible()) {
817       EXPECT_FALSE(GetButtonByID(added)->visible());
818       break;
819     }
820     last_visible = added;
821     ++items_added;
822     ASSERT_LT(items_added, 10000);
823   }
824
825   ShelfID panel = AddPanel();
826   EXPECT_TRUE(GetButtonByID(panel)->visible());
827   EXPECT_FALSE(GetButtonByID(last_visible)->visible());
828
829   RemoveByID(panel);
830   EXPECT_TRUE(GetButtonByID(last_visible)->visible());
831 }
832
833 // When there are more panels then platform app buttons we should hide panels
834 // rather than platform apps.
835 TEST_F(ShelfViewTest, PlatformAppHidesExcessPanels) {
836   // All buttons should be visible.
837   ASSERT_EQ(test_api_->GetButtonCount(),
838             test_api_->GetLastVisibleIndex() + 1);
839
840   // Add platform app button.
841   ShelfID platform_app = AddPlatformApp();
842   ShelfID first_panel = AddPanel();
843
844   EXPECT_TRUE(GetButtonByID(platform_app)->visible());
845   EXPECT_TRUE(GetButtonByID(first_panel)->visible());
846
847   // Add panels until there is an overflow.
848   ShelfID last_panel = first_panel;
849   int items_added = 0;
850   while (!test_api_->IsOverflowButtonVisible()) {
851     last_panel = AddPanel();
852     ++items_added;
853     ASSERT_LT(items_added, 10000);
854   }
855
856   // The first panel should now be hidden by the new platform apps needing
857   // space.
858   EXPECT_FALSE(GetButtonByID(first_panel)->visible());
859   EXPECT_TRUE(GetButtonByID(last_panel)->visible());
860   EXPECT_TRUE(GetButtonByID(platform_app)->visible());
861
862   // Adding platform apps should eventually begin to hide platform apps. We will
863   // add platform apps until either the last panel or platform app is hidden.
864   items_added = 0;
865   while (GetButtonByID(platform_app)->visible() &&
866          GetButtonByID(last_panel)->visible()) {
867     platform_app = AddPlatformApp();
868     ++items_added;
869     ASSERT_LT(items_added, 10000);
870   }
871   EXPECT_TRUE(GetButtonByID(last_panel)->visible());
872   EXPECT_FALSE(GetButtonByID(platform_app)->visible());
873 }
874
875 // Adds button until overflow then removes first added one. Verifies that
876 // the last added one changes from invisible to visible and overflow
877 // chevron is gone.
878 TEST_F(ShelfViewTest, RemoveButtonRevealsOverflowed) {
879   // All buttons should be visible.
880   ASSERT_EQ(test_api_->GetButtonCount(),
881             test_api_->GetLastVisibleIndex() + 1);
882
883   // Add platform app buttons until overflow.
884   int items_added = 0;
885   ShelfID first_added = AddPlatformApp();
886   ShelfID last_added = first_added;
887   while (!test_api_->IsOverflowButtonVisible()) {
888     last_added = AddPlatformApp();
889     ++items_added;
890     ASSERT_LT(items_added, 10000);
891   }
892
893   // Expect add more than 1 button. First added is visible and last is not.
894   EXPECT_NE(first_added, last_added);
895   EXPECT_TRUE(GetButtonByID(first_added)->visible());
896   EXPECT_FALSE(GetButtonByID(last_added)->visible());
897
898   // Remove first added.
899   RemoveByID(first_added);
900
901   // Last added button becomes visible and overflow chevron is gone.
902   EXPECT_TRUE(GetButtonByID(last_added)->visible());
903   EXPECT_EQ(1.0f, GetButtonByID(last_added)->layer()->opacity());
904   EXPECT_FALSE(test_api_->IsOverflowButtonVisible());
905 }
906
907 // Verifies that remove last overflowed button should hide overflow chevron.
908 TEST_F(ShelfViewTest, RemoveLastOverflowed) {
909   // All buttons should be visible.
910   ASSERT_EQ(test_api_->GetButtonCount(),
911             test_api_->GetLastVisibleIndex() + 1);
912
913   // Add platform app button until overflow.
914   int items_added = 0;
915   ShelfID last_added = AddPlatformApp();
916   while (!test_api_->IsOverflowButtonVisible()) {
917     last_added = AddPlatformApp();
918     ++items_added;
919     ASSERT_LT(items_added, 10000);
920   }
921
922   RemoveByID(last_added);
923   EXPECT_FALSE(test_api_->IsOverflowButtonVisible());
924 }
925
926 // Adds platform app button without waiting for animation to finish and verifies
927 // that all added buttons are visible.
928 TEST_F(ShelfViewTest, AddButtonQuickly) {
929   // All buttons should be visible.
930   ASSERT_EQ(test_api_->GetButtonCount(),
931             test_api_->GetLastVisibleIndex() + 1);
932
933   // Add a few platform buttons quickly without wait for animation.
934   int added_count = 0;
935   while (!test_api_->IsOverflowButtonVisible()) {
936     AddPlatformAppNoWait();
937     ++added_count;
938     ASSERT_LT(added_count, 10000);
939   }
940
941   // ShelfView should be big enough to hold at least 3 new buttons.
942   ASSERT_GE(added_count, 3);
943
944   // Wait for the last animation to finish.
945   test_api_->RunMessageLoopUntilAnimationsDone();
946
947   // Verifies non-overflow buttons are visible.
948   for (int i = 0; i <= test_api_->GetLastVisibleIndex(); ++i) {
949     internal::ShelfButton* button = test_api_->GetButton(i);
950     if (button) {
951       EXPECT_TRUE(button->visible()) << "button index=" << i;
952       EXPECT_EQ(1.0f, button->layer()->opacity()) << "button index=" << i;
953     }
954   }
955 }
956
957 // Check that model changes are handled correctly while a shelf icon is being
958 // dragged.
959 TEST_F(ShelfViewTest, ModelChangesWhileDragging) {
960   internal::ShelfButtonHost* button_host = shelf_view_;
961
962   std::vector<std::pair<ShelfID, views::View*> > id_map;
963   SetupForDragTest(&id_map);
964
965   // Dragging browser shortcut at index 1.
966   EXPECT_TRUE(model_->items()[1].type == TYPE_BROWSER_SHORTCUT);
967   views::View* dragged_button = SimulateDrag(
968       internal::ShelfButtonHost::MOUSE, 1, 3);
969   std::rotate(id_map.begin() + 1,
970               id_map.begin() + 2,
971               id_map.begin() + 4);
972   ASSERT_NO_FATAL_FAILURE(CheckModelIDs(id_map));
973   button_host->PointerReleasedOnButton(dragged_button,
974                                        internal::ShelfButtonHost::MOUSE,
975                                        false);
976   EXPECT_TRUE(model_->items()[3].type == TYPE_BROWSER_SHORTCUT);
977
978   // Dragging changes model order.
979   dragged_button = SimulateDrag(internal::ShelfButtonHost::MOUSE, 1, 3);
980   std::rotate(id_map.begin() + 1,
981               id_map.begin() + 2,
982               id_map.begin() + 4);
983   ASSERT_NO_FATAL_FAILURE(CheckModelIDs(id_map));
984
985   // Cancelling the drag operation restores previous order.
986   button_host->PointerReleasedOnButton(dragged_button,
987                                        internal::ShelfButtonHost::MOUSE,
988                                        true);
989   std::rotate(id_map.begin() + 1,
990               id_map.begin() + 3,
991               id_map.begin() + 4);
992   ASSERT_NO_FATAL_FAILURE(CheckModelIDs(id_map));
993
994   // Deleting an item keeps the remaining intact.
995   dragged_button = SimulateDrag(internal::ShelfButtonHost::MOUSE, 1, 3);
996   model_->RemoveItemAt(1);
997   id_map.erase(id_map.begin() + 1);
998   ASSERT_NO_FATAL_FAILURE(CheckModelIDs(id_map));
999   button_host->PointerReleasedOnButton(dragged_button,
1000                                        internal::ShelfButtonHost::MOUSE,
1001                                        false);
1002
1003   // Adding a shelf item cancels the drag and respects the order.
1004   dragged_button = SimulateDrag(internal::ShelfButtonHost::MOUSE, 1, 3);
1005   ShelfID new_id = AddAppShortcut();
1006   id_map.insert(id_map.begin() + 6,
1007                 std::make_pair(new_id, GetButtonByID(new_id)));
1008   ASSERT_NO_FATAL_FAILURE(CheckModelIDs(id_map));
1009   button_host->PointerReleasedOnButton(dragged_button,
1010                                        internal::ShelfButtonHost::MOUSE,
1011                                        false);
1012
1013   // Adding a shelf item at the end (i.e. a panel)  canels drag and respects
1014   // the order.
1015   dragged_button = SimulateDrag(internal::ShelfButtonHost::MOUSE, 1, 3);
1016   new_id = AddPanel();
1017   id_map.insert(id_map.begin() + 7,
1018                 std::make_pair(new_id, GetButtonByID(new_id)));
1019   ASSERT_NO_FATAL_FAILURE(CheckModelIDs(id_map));
1020   button_host->PointerReleasedOnButton(dragged_button,
1021                                        internal::ShelfButtonHost::MOUSE,
1022                                        false);
1023 }
1024
1025 TEST_F(ShelfViewLegacyShelfLayoutTest, ModelChangesWhileDragging) {
1026   internal::ShelfButtonHost* button_host = shelf_view_;
1027
1028   std::vector<std::pair<ShelfID, views::View*> > id_map;
1029   SetupForDragTest(&id_map);
1030
1031   // Dragging browser shortcut at index 0.
1032   EXPECT_TRUE(model_->items()[0].type == TYPE_BROWSER_SHORTCUT);
1033   views::View* dragged_button = SimulateDrag(
1034       internal::ShelfButtonHost::MOUSE, 0, 2);
1035   std::rotate(id_map.begin(),
1036               id_map.begin() + 1,
1037               id_map.begin() + 3);
1038   ASSERT_NO_FATAL_FAILURE(CheckModelIDs(id_map));
1039   button_host->PointerReleasedOnButton(dragged_button,
1040                                        internal::ShelfButtonHost::MOUSE,
1041                                        false);
1042   EXPECT_TRUE(model_->items()[2].type == TYPE_BROWSER_SHORTCUT);
1043
1044   // Dragging changes model order.
1045   dragged_button = SimulateDrag(internal::ShelfButtonHost::MOUSE, 0, 2);
1046   std::rotate(id_map.begin(),
1047               id_map.begin() + 1,
1048               id_map.begin() + 3);
1049   ASSERT_NO_FATAL_FAILURE(CheckModelIDs(id_map));
1050
1051   // Cancelling the drag operation restores previous order.
1052   button_host->PointerReleasedOnButton(dragged_button,
1053                                        internal::ShelfButtonHost::MOUSE,
1054                                        true);
1055   std::rotate(id_map.begin(),
1056               id_map.begin() + 2,
1057               id_map.begin() + 3);
1058   ASSERT_NO_FATAL_FAILURE(CheckModelIDs(id_map));
1059
1060   // Deleting an item keeps the remaining intact.
1061   dragged_button = SimulateDrag(internal::ShelfButtonHost::MOUSE, 0, 2);
1062   model_->RemoveItemAt(1);
1063   id_map.erase(id_map.begin() + 1);
1064   ASSERT_NO_FATAL_FAILURE(CheckModelIDs(id_map));
1065   button_host->PointerReleasedOnButton(dragged_button,
1066                                        internal::ShelfButtonHost::MOUSE,
1067                                        false);
1068
1069   // Adding a shelf item cancels the drag and respects the order.
1070   dragged_button = SimulateDrag(internal::ShelfButtonHost::MOUSE, 0, 2);
1071   ShelfID new_id = AddAppShortcut();
1072   id_map.insert(id_map.begin() + 5,
1073                 std::make_pair(new_id, GetButtonByID(new_id)));
1074   ASSERT_NO_FATAL_FAILURE(CheckModelIDs(id_map));
1075   button_host->PointerReleasedOnButton(dragged_button,
1076                                        internal::ShelfButtonHost::MOUSE,
1077                                        false);
1078
1079   // Adding a shelf item at the end (i.e. a panel)  canels drag and respects
1080   // the order.
1081   dragged_button = SimulateDrag(internal::ShelfButtonHost::MOUSE, 0, 2);
1082   new_id = AddPanel();
1083   id_map.insert(id_map.begin() + 7,
1084                 std::make_pair(new_id, GetButtonByID(new_id)));
1085   ASSERT_NO_FATAL_FAILURE(CheckModelIDs(id_map));
1086   button_host->PointerReleasedOnButton(dragged_button,
1087                                        internal::ShelfButtonHost::MOUSE,
1088                                        false);
1089 }
1090
1091 // Check that 2nd drag from the other pointer would be ignored.
1092 TEST_F(ShelfViewTest, SimultaneousDrag) {
1093   internal::ShelfButtonHost* button_host = shelf_view_;
1094
1095   std::vector<std::pair<ShelfID, views::View*> > id_map;
1096   SetupForDragTest(&id_map);
1097
1098   // Start a mouse drag.
1099   views::View* dragged_button_mouse = SimulateDrag(
1100       internal::ShelfButtonHost::MOUSE, 1, 3);
1101   std::rotate(id_map.begin() + 1,
1102               id_map.begin() + 2,
1103               id_map.begin() + 4);
1104   ASSERT_NO_FATAL_FAILURE(CheckModelIDs(id_map));
1105   // Attempt a touch drag before the mouse drag finishes.
1106   views::View* dragged_button_touch = SimulateDrag(
1107       internal::ShelfButtonHost::TOUCH, 4, 2);
1108
1109   // Nothing changes since 2nd drag is ignored.
1110   ASSERT_NO_FATAL_FAILURE(CheckModelIDs(id_map));
1111
1112   // Finish the mouse drag.
1113   button_host->PointerReleasedOnButton(dragged_button_mouse,
1114                                        internal::ShelfButtonHost::MOUSE,
1115                                        false);
1116   ASSERT_NO_FATAL_FAILURE(CheckModelIDs(id_map));
1117
1118   // Now start a touch drag.
1119   dragged_button_touch = SimulateDrag(internal::ShelfButtonHost::TOUCH, 4, 2);
1120   std::rotate(id_map.begin() + 3,
1121               id_map.begin() + 4,
1122               id_map.begin() + 5);
1123   ASSERT_NO_FATAL_FAILURE(CheckModelIDs(id_map));
1124
1125   // And attempt a mouse drag before the touch drag finishes.
1126   dragged_button_mouse = SimulateDrag(internal::ShelfButtonHost::MOUSE, 1, 2);
1127
1128   // Nothing changes since 2nd drag is ignored.
1129   ASSERT_NO_FATAL_FAILURE(CheckModelIDs(id_map));
1130
1131   button_host->PointerReleasedOnButton(dragged_button_touch,
1132                                        internal::ShelfButtonHost::TOUCH,
1133                                        false);
1134   ASSERT_NO_FATAL_FAILURE(CheckModelIDs(id_map));
1135 }
1136
1137 // Check that clicking first on one item and then dragging another works as
1138 // expected.
1139 TEST_F(ShelfViewTest, ClickOneDragAnother) {
1140   internal::ShelfButtonHost* button_host = shelf_view_;
1141
1142   std::vector<std::pair<ShelfID, views::View*> > id_map;
1143   SetupForDragTest(&id_map);
1144
1145   // A click on item 1 is simulated.
1146   SimulateClick(internal::ShelfButtonHost::MOUSE, 1);
1147
1148   // Dragging browser index at 0 should change the model order correctly.
1149   EXPECT_TRUE(model_->items()[1].type == TYPE_BROWSER_SHORTCUT);
1150   views::View* dragged_button = SimulateDrag(
1151       internal::ShelfButtonHost::MOUSE, 1, 3);
1152   std::rotate(id_map.begin() + 1,
1153               id_map.begin() + 2,
1154               id_map.begin() + 4);
1155   ASSERT_NO_FATAL_FAILURE(CheckModelIDs(id_map));
1156   button_host->PointerReleasedOnButton(dragged_button,
1157                                        internal::ShelfButtonHost::MOUSE,
1158                                        false);
1159   EXPECT_TRUE(model_->items()[3].type == TYPE_BROWSER_SHORTCUT);
1160 }
1161
1162 // Confirm that item status changes are reflected in the buttons.
1163 TEST_F(ShelfViewTest, ShelfItemStatus) {
1164   // All buttons should be visible.
1165   ASSERT_EQ(test_api_->GetButtonCount(),
1166             test_api_->GetLastVisibleIndex() + 1);
1167
1168   // Add platform app button.
1169   ShelfID last_added = AddPlatformApp();
1170   ShelfItem item = GetItemByID(last_added);
1171   int index = model_->ItemIndexByID(last_added);
1172   internal::ShelfButton* button = GetButtonByID(last_added);
1173   ASSERT_EQ(internal::ShelfButton::STATE_RUNNING, button->state());
1174   item.status = STATUS_ACTIVE;
1175   model_->Set(index, item);
1176   ASSERT_EQ(internal::ShelfButton::STATE_ACTIVE, button->state());
1177   item.status = STATUS_ATTENTION;
1178   model_->Set(index, item);
1179   ASSERT_EQ(internal::ShelfButton::STATE_ATTENTION, button->state());
1180 }
1181
1182 TEST_F(ShelfViewLegacyShelfLayoutTest,
1183        ShelfItemPositionReflectedOnStateChanged) {
1184   // All buttons should be visible.
1185   ASSERT_EQ(test_api_->GetButtonCount(),
1186             test_api_->GetLastVisibleIndex() + 1);
1187
1188   // Add 2 items to the shelf.
1189   ShelfID item1_id = AddPlatformApp();
1190   ShelfID item2_id = AddPlatformAppNoWait();
1191   internal::ShelfButton* item1_button = GetButtonByID(item1_id);
1192   internal::ShelfButton* item2_button = GetButtonByID(item2_id);
1193
1194   internal::ShelfButton::State state_mask =
1195       static_cast<internal::ShelfButton::State>(
1196           internal::ShelfButton::STATE_NORMAL |
1197           internal::ShelfButton::STATE_HOVERED |
1198           internal::ShelfButton::STATE_RUNNING |
1199           internal::ShelfButton::STATE_ACTIVE |
1200           internal::ShelfButton::STATE_ATTENTION |
1201           internal::ShelfButton::STATE_FOCUSED);
1202
1203   // Clear the button states.
1204   item1_button->ClearState(state_mask);
1205   item2_button->ClearState(state_mask);
1206
1207   // Since default alignment in tests is bottom, state is reflected in y-axis.
1208   ASSERT_EQ(item1_button->GetIconBounds().y(),
1209             item2_button->GetIconBounds().y());
1210   item1_button->AddState(internal::ShelfButton::STATE_HOVERED);
1211   ASSERT_NE(item1_button->GetIconBounds().y(),
1212             item2_button->GetIconBounds().y());
1213   item1_button->ClearState(internal::ShelfButton::STATE_HOVERED);
1214 }
1215
1216 // Confirm that item status changes are reflected in the buttons
1217 // for platform apps.
1218 TEST_F(ShelfViewTest, ShelfItemStatusPlatformApp) {
1219   // All buttons should be visible.
1220   ASSERT_EQ(test_api_->GetButtonCount(),
1221             test_api_->GetLastVisibleIndex() + 1);
1222
1223   // Add platform app button.
1224   ShelfID last_added = AddPlatformApp();
1225   ShelfItem item = GetItemByID(last_added);
1226   int index = model_->ItemIndexByID(last_added);
1227   internal::ShelfButton* button = GetButtonByID(last_added);
1228   ASSERT_EQ(internal::ShelfButton::STATE_RUNNING, button->state());
1229   item.status = STATUS_ACTIVE;
1230   model_->Set(index, item);
1231   ASSERT_EQ(internal::ShelfButton::STATE_ACTIVE, button->state());
1232   item.status = STATUS_ATTENTION;
1233   model_->Set(index, item);
1234   ASSERT_EQ(internal::ShelfButton::STATE_ATTENTION, button->state());
1235 }
1236
1237 // Confirm that shelf item bounds are correctly updated on shelf changes.
1238 TEST_F(ShelfViewTest, ShelfItemBoundsCheck) {
1239   VerifyShelfItemBoundsAreValid();
1240   shelf_view_->shelf_layout_manager()->SetAutoHideBehavior(
1241       SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS);
1242   test_api_->RunMessageLoopUntilAnimationsDone();
1243   VerifyShelfItemBoundsAreValid();
1244   shelf_view_->shelf_layout_manager()->SetAutoHideBehavior(
1245       SHELF_AUTO_HIDE_BEHAVIOR_NEVER);
1246   test_api_->RunMessageLoopUntilAnimationsDone();
1247   VerifyShelfItemBoundsAreValid();
1248 }
1249
1250 TEST_F(ShelfViewTest, ShelfTooltipTest) {
1251   ASSERT_EQ(test_api_->GetLastVisibleIndex() + 1,
1252             test_api_->GetButtonCount());
1253
1254   // Prepare some items to the shelf.
1255   ShelfID app_button_id = AddAppShortcut();
1256   ShelfID platform_button_id = AddPlatformApp();
1257
1258   internal::ShelfButton* app_button = GetButtonByID(app_button_id);
1259   internal::ShelfButton* platform_button = GetButtonByID(platform_button_id);
1260
1261   internal::ShelfButtonHost* button_host = shelf_view_;
1262   internal::ShelfTooltipManager* tooltip_manager =
1263       shelf_view_->tooltip_manager();
1264
1265   button_host->MouseEnteredButton(app_button);
1266   // There's a delay to show the tooltip, so it's not visible yet.
1267   EXPECT_FALSE(tooltip_manager->IsVisible());
1268   EXPECT_EQ(app_button, GetTooltipAnchorView());
1269
1270   ShowTooltip();
1271   EXPECT_TRUE(tooltip_manager->IsVisible());
1272
1273   // Once it's visible, it keeps visibility and is pointing to the same
1274   // item.
1275   button_host->MouseExitedButton(app_button);
1276   EXPECT_TRUE(tooltip_manager->IsVisible());
1277   EXPECT_EQ(app_button, GetTooltipAnchorView());
1278
1279   // When entered to another item, it switches to the new item.  There is no
1280   // delay for the visibility.
1281   button_host->MouseEnteredButton(platform_button);
1282   EXPECT_TRUE(tooltip_manager->IsVisible());
1283   EXPECT_EQ(platform_button, GetTooltipAnchorView());
1284
1285   button_host->MouseExitedButton(platform_button);
1286   tooltip_manager->Close();
1287
1288   // Next time: enter app_button -> move immediately to tab_button.
1289   button_host->MouseEnteredButton(app_button);
1290   button_host->MouseExitedButton(app_button);
1291   button_host->MouseEnteredButton(platform_button);
1292   EXPECT_FALSE(tooltip_manager->IsVisible());
1293   EXPECT_EQ(platform_button, GetTooltipAnchorView());
1294 }
1295
1296 // Verify a fix for crash caused by a tooltip update for a deletedshelf
1297 // button, see crbug.com/288838.
1298 TEST_F(ShelfViewTest, RemovingItemClosesTooltip) {
1299   internal::ShelfButtonHost* button_host = shelf_view_;
1300   internal::ShelfTooltipManager* tooltip_manager =
1301       shelf_view_->tooltip_manager();
1302
1303   // Add an item to the shelf.
1304   ShelfID app_button_id = AddAppShortcut();
1305   internal::ShelfButton* app_button = GetButtonByID(app_button_id);
1306
1307   // Spawn a tooltip on that item.
1308   button_host->MouseEnteredButton(app_button);
1309   ShowTooltip();
1310   EXPECT_TRUE(tooltip_manager->IsVisible());
1311
1312   // Remove the app shortcut while the tooltip is open. The tooltip should be
1313   // closed.
1314   RemoveByID(app_button_id);
1315   EXPECT_FALSE(tooltip_manager->IsVisible());
1316
1317   // Change the shelf layout. This should not crash.
1318   Shell::GetInstance()->SetShelfAlignment(SHELF_ALIGNMENT_LEFT,
1319                                           Shell::GetPrimaryRootWindow());
1320 }
1321
1322 // Changing the shelf alignment closes any open tooltip.
1323 TEST_F(ShelfViewTest, ShelfAlignmentClosesTooltip) {
1324   internal::ShelfButtonHost* button_host = shelf_view_;
1325   internal::ShelfTooltipManager* tooltip_manager =
1326       shelf_view_->tooltip_manager();
1327
1328   // Add an item to the shelf.
1329   ShelfID app_button_id = AddAppShortcut();
1330   internal::ShelfButton* app_button = GetButtonByID(app_button_id);
1331
1332   // Spawn a tooltip on the item.
1333   button_host->MouseEnteredButton(app_button);
1334   ShowTooltip();
1335   EXPECT_TRUE(tooltip_manager->IsVisible());
1336
1337   // Changing shelf alignment hides the tooltip.
1338   Shell::GetInstance()->SetShelfAlignment(SHELF_ALIGNMENT_LEFT,
1339                                           Shell::GetPrimaryRootWindow());
1340   EXPECT_FALSE(tooltip_manager->IsVisible());
1341 }
1342
1343 TEST_F(ShelfViewTest, ShouldHideTooltipTest) {
1344   ShelfID app_button_id = AddAppShortcut();
1345   ShelfID platform_button_id = AddPlatformApp();
1346
1347   // The tooltip shouldn't hide if the mouse is on normal buttons.
1348   for (int i = 0; i < test_api_->GetButtonCount(); i++) {
1349     internal::ShelfButton* button = test_api_->GetButton(i);
1350     if (!button)
1351       continue;
1352
1353     EXPECT_FALSE(shelf_view_->ShouldHideTooltip(
1354         button->GetMirroredBounds().CenterPoint()))
1355         << "ShelfView tries to hide on button " << i;
1356   }
1357
1358   // The tooltip should not hide on the app-list button.
1359   views::View* app_list_button = shelf_view_->GetAppListButtonView();
1360   EXPECT_FALSE(shelf_view_->ShouldHideTooltip(
1361       app_list_button->GetMirroredBounds().CenterPoint()));
1362
1363   // The tooltip shouldn't hide if the mouse is in the gap between two buttons.
1364   gfx::Rect app_button_rect = GetButtonByID(app_button_id)->GetMirroredBounds();
1365   gfx::Rect platform_button_rect =
1366       GetButtonByID(platform_button_id)->GetMirroredBounds();
1367   ASSERT_FALSE(app_button_rect.Intersects(platform_button_rect));
1368   EXPECT_FALSE(shelf_view_->ShouldHideTooltip(
1369       gfx::UnionRects(app_button_rect, platform_button_rect).CenterPoint()));
1370
1371   // The tooltip should hide if it's outside of all buttons.
1372   gfx::Rect all_area;
1373   for (int i = 0; i < test_api_->GetButtonCount(); i++) {
1374     internal::ShelfButton* button = test_api_->GetButton(i);
1375     if (!button)
1376       continue;
1377
1378     all_area.Union(button->GetMirroredBounds());
1379   }
1380   all_area.Union(shelf_view_->GetAppListButtonView()->GetMirroredBounds());
1381   EXPECT_FALSE(shelf_view_->ShouldHideTooltip(all_area.origin()));
1382   EXPECT_FALSE(shelf_view_->ShouldHideTooltip(
1383       gfx::Point(all_area.right() - 1, all_area.bottom() - 1)));
1384   EXPECT_TRUE(shelf_view_->ShouldHideTooltip(
1385       gfx::Point(all_area.right(), all_area.y())));
1386   EXPECT_TRUE(shelf_view_->ShouldHideTooltip(
1387       gfx::Point(all_area.x() - 1, all_area.y())));
1388   EXPECT_TRUE(shelf_view_->ShouldHideTooltip(
1389       gfx::Point(all_area.x(), all_area.y() - 1)));
1390   EXPECT_TRUE(shelf_view_->ShouldHideTooltip(
1391       gfx::Point(all_area.x(), all_area.bottom())));
1392 }
1393
1394 TEST_F(ShelfViewTest, ShouldHideTooltipWithAppListWindowTest) {
1395   Shell::GetInstance()->ToggleAppList(NULL);
1396   ASSERT_TRUE(Shell::GetInstance()->GetAppListWindow());
1397
1398   // The tooltip shouldn't hide if the mouse is on normal buttons.
1399   for (int i = 1; i < test_api_->GetButtonCount(); i++) {
1400     internal::ShelfButton* button = test_api_->GetButton(i);
1401     if (!button)
1402       continue;
1403
1404     EXPECT_FALSE(shelf_view_->ShouldHideTooltip(
1405         button->GetMirroredBounds().CenterPoint()))
1406         << "ShelfView tries to hide on button " << i;
1407   }
1408
1409   // The tooltip should hide on the app-list button.
1410   views::View* app_list_button = shelf_view_->GetAppListButtonView();
1411   EXPECT_TRUE(shelf_view_->ShouldHideTooltip(
1412       app_list_button->GetMirroredBounds().CenterPoint()));
1413 }
1414
1415 // Test that by moving the mouse cursor off the button onto the bubble it closes
1416 // the bubble.
1417 TEST_F(ShelfViewTest, ShouldHideTooltipWhenHoveringOnTooltip) {
1418   internal::ShelfTooltipManager* tooltip_manager =
1419       shelf_view_->tooltip_manager();
1420   tooltip_manager->CreateZeroDelayTimerForTest();
1421   aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow());
1422
1423   // Move the mouse off any item and check that no tooltip is shown.
1424   generator.MoveMouseTo(gfx::Point(0, 0));
1425   EXPECT_FALSE(tooltip_manager->IsVisible());
1426
1427   // Move the mouse over the button and check that it is visible.
1428   views::View* app_list_button = shelf_view_->GetAppListButtonView();
1429   gfx::Rect bounds = app_list_button->GetBoundsInScreen();
1430   generator.MoveMouseTo(bounds.CenterPoint());
1431   // Wait for the timer to go off.
1432   RunAllPendingInMessageLoop();
1433   EXPECT_TRUE(tooltip_manager->IsVisible());
1434
1435   // Move the mouse cursor slightly to the right of the item. The tooltip should
1436   // stay open.
1437   generator.MoveMouseBy(bounds.width() / 2 + 5, 0);
1438   // Make sure there is no delayed close.
1439   RunAllPendingInMessageLoop();
1440   EXPECT_TRUE(tooltip_manager->IsVisible());
1441
1442   // Move back - it should still stay open.
1443   generator.MoveMouseBy(-(bounds.width() / 2 + 5), 0);
1444   // Make sure there is no delayed close.
1445   RunAllPendingInMessageLoop();
1446   EXPECT_TRUE(tooltip_manager->IsVisible());
1447
1448   // Now move the mouse cursor slightly above the item - so that it is over the
1449   // tooltip bubble. Now it should disappear.
1450   generator.MoveMouseBy(0, -(bounds.height() / 2 + 5));
1451   // Wait until the delayed close kicked in.
1452   RunAllPendingInMessageLoop();
1453   EXPECT_FALSE(tooltip_manager->IsVisible());
1454 }
1455
1456 // Resizing shelf view while an add animation without fade-in is running,
1457 // which happens when overflow happens. App list button should end up in its
1458 // new ideal bounds.
1459 TEST_F(ShelfViewTest, ResizeDuringOverflowAddAnimation) {
1460   // All buttons should be visible.
1461   ASSERT_EQ(test_api_->GetButtonCount(),
1462             test_api_->GetLastVisibleIndex() + 1);
1463
1464   // Add buttons until overflow. Let the non-overflow add animations finish but
1465   // leave the last running.
1466   int items_added = 0;
1467   AddPlatformAppNoWait();
1468   while (!test_api_->IsOverflowButtonVisible()) {
1469     test_api_->RunMessageLoopUntilAnimationsDone();
1470     AddPlatformAppNoWait();
1471     ++items_added;
1472     ASSERT_LT(items_added, 10000);
1473   }
1474
1475   // Resize shelf view with that animation running and stay overflown.
1476   gfx::Rect bounds = shelf_view_->bounds();
1477   bounds.set_width(bounds.width() - kShelfPreferredSize);
1478   shelf_view_->SetBoundsRect(bounds);
1479   ASSERT_TRUE(test_api_->IsOverflowButtonVisible());
1480
1481   // Finish the animation.
1482   test_api_->RunMessageLoopUntilAnimationsDone();
1483
1484   // App list button should ends up in its new ideal bounds.
1485   const int app_list_button_index = test_api_->GetButtonCount() - 1;
1486   const gfx::Rect& app_list_ideal_bounds =
1487       test_api_->GetIdealBoundsByIndex(app_list_button_index);
1488   const gfx::Rect& app_list_bounds =
1489       test_api_->GetBoundsByIndex(app_list_button_index);
1490   EXPECT_EQ(app_list_ideal_bounds, app_list_bounds);
1491 }
1492
1493 // Checks the overflow bubble size when an item is ripped off and re-inserted.
1494 TEST_F(ShelfViewTest, OverflowBubbleSize) {
1495   // Replace current ShelfDelegate with TestShelfDelegateForShelfView.
1496   ReplaceShelfDelegateForRipOffTest();
1497
1498   AddButtonsUntilOverflow();
1499
1500   // Show overflow bubble.
1501   test_api_->ShowOverflowBubble();
1502   ASSERT_TRUE(test_api_->overflow_bubble() &&
1503               test_api_->overflow_bubble()->IsShowing());
1504
1505   ShelfViewTestAPI test_for_overflow_view(
1506       test_api_->overflow_bubble()->shelf_view());
1507
1508   int ripped_index = test_for_overflow_view.GetLastVisibleIndex();
1509   gfx::Size bubble_size = test_for_overflow_view.GetPreferredSize();
1510   int item_width = test_for_overflow_view.GetButtonSize() +
1511       test_for_overflow_view.GetButtonSpacing();
1512
1513   aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow(),
1514                                        gfx::Point());
1515   internal::ShelfButton* button =
1516       test_for_overflow_view.GetButton(ripped_index);
1517   // Rip off the last visible item.
1518   gfx::Point start_point = button->GetBoundsInScreen().CenterPoint();
1519   gfx::Point rip_off_point(start_point.x(), 0);
1520   generator.MoveMouseTo(start_point.x(), start_point.y());
1521   base::MessageLoop::current()->RunUntilIdle();
1522   generator.PressLeftButton();
1523   base::MessageLoop::current()->RunUntilIdle();
1524   generator.MoveMouseTo(rip_off_point.x(), rip_off_point.y());
1525   base::MessageLoop::current()->RunUntilIdle();
1526   test_for_overflow_view.RunMessageLoopUntilAnimationsDone();
1527
1528   // Check the overflow bubble size when an item is ripped off.
1529   EXPECT_EQ(bubble_size.width() - item_width,
1530             test_for_overflow_view.GetPreferredSize().width());
1531   ASSERT_TRUE(test_api_->overflow_bubble() &&
1532               test_api_->overflow_bubble()->IsShowing());
1533
1534   // Re-insert an item into the overflow bubble.
1535   int first_index = test_for_overflow_view.GetFirstVisibleIndex();
1536   button = test_for_overflow_view.GetButton(first_index);
1537
1538   // Check the bubble size after an item is re-inserted.
1539   generator.MoveMouseTo(button->GetBoundsInScreen().CenterPoint());
1540   test_for_overflow_view.RunMessageLoopUntilAnimationsDone();
1541   EXPECT_EQ(bubble_size.width(),
1542             test_for_overflow_view.GetPreferredSize().width());
1543
1544   generator.ReleaseLeftButton();
1545   test_for_overflow_view.RunMessageLoopUntilAnimationsDone();
1546   EXPECT_EQ(bubble_size.width(),
1547             test_for_overflow_view.GetPreferredSize().width());
1548 }
1549
1550 // Check that the first item in the list follows Fitt's law by including the
1551 // first pixel and being therefore bigger then the others.
1552 TEST_F(ShelfViewLegacyShelfLayoutTest, CheckFittsLaw) {
1553   // All buttons should be visible.
1554   ASSERT_EQ(test_api_->GetButtonCount(),
1555             test_api_->GetLastVisibleIndex() + 1);
1556   gfx::Rect ideal_bounds_0 = test_api_->GetIdealBoundsByIndex(0);
1557   gfx::Rect ideal_bounds_1 = test_api_->GetIdealBoundsByIndex(1);
1558   EXPECT_GT(ideal_bounds_0.width(), ideal_bounds_1.width());
1559 }
1560
1561 // Check the drag insertion bounds of scrolled overflow bubble.
1562 TEST_F(ShelfViewTest, CheckDragInsertBoundsOfScrolledOverflowBubble) {
1563   UpdateDisplay("400x300");
1564
1565   EXPECT_EQ(2, model_->item_count());
1566
1567   AddButtonsUntilOverflow();
1568
1569   // Show overflow bubble.
1570   test_api_->ShowOverflowBubble();
1571   ASSERT_TRUE(test_api_->overflow_bubble() &&
1572               test_api_->overflow_bubble()->IsShowing());
1573
1574   int item_width = test_api_->GetButtonSize() +
1575       test_api_->GetButtonSpacing();
1576   internal::OverflowBubbleView* bubble_view =
1577       test_api_->overflow_bubble()->bubble_view();
1578   test::OverflowBubbleViewTestAPI bubble_view_api(bubble_view);
1579
1580   // Add more buttons until OverflowBubble is scrollable and it has 3 invisible
1581   // items.
1582   while (bubble_view_api.GetContentsSize().width() <
1583          (bubble_view->GetContentsBounds().width() + 3 * item_width))
1584     AddAppShortcut();
1585
1586   ASSERT_TRUE(test_api_->overflow_bubble() &&
1587               test_api_->overflow_bubble()->IsShowing());
1588
1589   ShelfViewTestAPI test_for_overflow_view(
1590       test_api_->overflow_bubble()->shelf_view());
1591   int first_index = test_for_overflow_view.GetFirstVisibleIndex();
1592   int last_index = test_for_overflow_view.GetLastVisibleIndex();
1593
1594   internal::ShelfButton* first_button =
1595       test_for_overflow_view.GetButton(first_index);
1596   internal::ShelfButton* last_button =
1597       test_for_overflow_view.GetButton(last_index);
1598   gfx::Point first_point = first_button->GetBoundsInScreen().CenterPoint();
1599   gfx::Point last_point = last_button->GetBoundsInScreen().CenterPoint();
1600   gfx::Rect drag_reinsert_bounds =
1601       test_for_overflow_view.GetBoundsForDragInsertInScreen();
1602   EXPECT_TRUE(drag_reinsert_bounds.Contains(first_point));
1603   EXPECT_FALSE(drag_reinsert_bounds.Contains(last_point));
1604
1605   // Scrolls sufficiently to show last item.
1606   bubble_view_api.ScrollByXOffset(3 * item_width);
1607   drag_reinsert_bounds =
1608       test_for_overflow_view.GetBoundsForDragInsertInScreen();
1609   first_point = first_button->GetBoundsInScreen().CenterPoint();
1610   last_point = last_button->GetBoundsInScreen().CenterPoint();
1611   EXPECT_FALSE(drag_reinsert_bounds.Contains(first_point));
1612   EXPECT_TRUE(drag_reinsert_bounds.Contains(last_point));
1613 }
1614
1615 // Check the drag insertion bounds of shelf view in multi monitor environment.
1616 TEST_F(ShelfViewTest, CheckDragInsertBoundsWithMultiMonitor) {
1617   // win8-aura doesn't support multiple display.
1618   if (!SupportsMultipleDisplays())
1619     return;
1620
1621   UpdateDisplay("800x600,800x600");
1622   Shelf* secondary_shelf = Shelf::ForWindow(Shell::GetAllRootWindows()[1]);
1623   internal::ShelfView* shelf_view_for_secondary =
1624       ShelfTestAPI(secondary_shelf).shelf_view();
1625
1626   // The bounds should be big enough for 4 buttons + overflow chevron.
1627   shelf_view_for_secondary->SetBounds(0, 0, 500,
1628       internal::ShelfLayoutManager::GetPreferredShelfSize());
1629
1630   ShelfViewTestAPI test_api_for_secondary(shelf_view_for_secondary);
1631   // Speeds up animation for test.
1632   test_api_for_secondary.SetAnimationDuration(1);
1633
1634   AddButtonsUntilOverflow();
1635
1636   // Test #1: Test drag insertion bounds of primary shelf.
1637   // Show overflow bubble.
1638   test_api_->ShowOverflowBubble();
1639   ASSERT_TRUE(test_api_->overflow_bubble() &&
1640               test_api_->overflow_bubble()->IsShowing());
1641
1642   ShelfViewTestAPI test_api_for_overflow_view(
1643       test_api_->overflow_bubble()->shelf_view());
1644
1645   internal::ShelfButton* button = test_api_for_overflow_view.GetButton(
1646       test_api_for_overflow_view.GetLastVisibleIndex());
1647
1648   // Checks that a point in shelf is contained in drag insert bounds.
1649   gfx::Point point_in_shelf_view = button->GetBoundsInScreen().CenterPoint();
1650   gfx::Rect drag_reinsert_bounds =
1651       test_api_for_overflow_view.GetBoundsForDragInsertInScreen();
1652   EXPECT_TRUE(drag_reinsert_bounds.Contains(point_in_shelf_view));
1653   // Checks that a point out of shelf is not contained in drag insert bounds.
1654   EXPECT_FALSE(drag_reinsert_bounds.Contains(
1655       gfx::Point(point_in_shelf_view.x(), 0)));
1656
1657   // Test #2: Test drag insertion bounds of secondary shelf.
1658   // Show overflow bubble.
1659   test_api_for_secondary.ShowOverflowBubble();
1660   ASSERT_TRUE(test_api_for_secondary.overflow_bubble() &&
1661               test_api_for_secondary.overflow_bubble()->IsShowing());
1662
1663   ShelfViewTestAPI test_api_for_overflow_view_of_secondary(
1664       test_api_for_secondary.overflow_bubble()->shelf_view());
1665
1666   internal::ShelfButton* button_in_secondary =
1667       test_api_for_overflow_view_of_secondary.GetButton(
1668           test_api_for_overflow_view_of_secondary.GetLastVisibleIndex());
1669
1670   // Checks that a point in shelf is contained in drag insert bounds.
1671   gfx::Point point_in_secondary_shelf_view =
1672       button_in_secondary->GetBoundsInScreen().CenterPoint();
1673   gfx::Rect drag_reinsert_bounds_in_secondary =
1674       test_api_for_overflow_view_of_secondary.GetBoundsForDragInsertInScreen();
1675   EXPECT_TRUE(drag_reinsert_bounds_in_secondary.Contains(
1676       point_in_secondary_shelf_view));
1677   // Checks that a point out of shelf is not contained in drag insert bounds.
1678   EXPECT_FALSE(drag_reinsert_bounds_in_secondary.Contains(
1679       gfx::Point(point_in_secondary_shelf_view.x(), 0)));
1680   // Checks that a point of overflow bubble in primary shelf should not be
1681   // contained by insert bounds of secondary shelf.
1682   EXPECT_FALSE(drag_reinsert_bounds_in_secondary.Contains(point_in_shelf_view));
1683 }
1684
1685 // Checks the rip an item off from left aligned shelf in secondary monitor.
1686 TEST_F(ShelfViewTest, CheckRipOffFromLeftShelfAlignmentWithMultiMonitor) {
1687   // win8-aura doesn't support multiple display.
1688   if (!SupportsMultipleDisplays())
1689     return;
1690
1691   UpdateDisplay("800x600,800x600");
1692   ASSERT_EQ(2U, Shell::GetAllRootWindows().size());
1693
1694   aura::Window* second_root = Shell::GetAllRootWindows()[1];
1695
1696   Shell::GetInstance()->SetShelfAlignment(SHELF_ALIGNMENT_LEFT, second_root);
1697   ASSERT_EQ(SHELF_ALIGNMENT_LEFT,
1698             Shell::GetInstance()->GetShelfAlignment(second_root));
1699
1700   // Initially, app list and browser shortcut are added.
1701   EXPECT_EQ(2, model_->item_count());
1702   int browser_index = model_->GetItemIndexForType(TYPE_BROWSER_SHORTCUT);
1703   EXPECT_GT(browser_index, 0);
1704
1705   Shelf* secondary_shelf = Shelf::ForWindow(second_root);
1706   internal::ShelfView* shelf_view_for_secondary =
1707       ShelfTestAPI(secondary_shelf).shelf_view();
1708
1709   ShelfViewTestAPI test_api_for_secondary_shelf_view(shelf_view_for_secondary);
1710   internal::ShelfButton* button =
1711     test_api_for_secondary_shelf_view.GetButton(browser_index);
1712
1713   // Fetch the start point of dragging.
1714   gfx::Point start_point = button->GetBoundsInScreen().CenterPoint();
1715   wm::ConvertPointFromScreen(second_root, &start_point);
1716
1717   aura::test::EventGenerator generator(second_root, start_point);
1718
1719   // Rip off the browser item.
1720   generator.PressLeftButton();
1721   generator.MoveMouseTo(start_point.x() + 400, start_point.y());
1722   test_api_for_secondary_shelf_view.RunMessageLoopUntilAnimationsDone();
1723   EXPECT_TRUE(test_api_for_secondary_shelf_view.IsRippedOffFromShelf());
1724 }
1725
1726 // Checks various drag and drop operations from OverflowBubble to Shelf.
1727 TEST_F(ShelfViewTest, CheckDragAndDropFromOverflowBubbleToShelf) {
1728   // Replace current ShelfDelegate with TestShelfDelegateForShelfView.
1729   ReplaceShelfDelegateForRipOffTest();
1730
1731   AddButtonsUntilOverflow();
1732
1733   TestDraggingAnItemFromOverflowToShelf(false);
1734   TestDraggingAnItemFromOverflowToShelf(true);
1735 }
1736
1737 class ShelfViewVisibleBoundsTest : public ShelfViewTest,
1738                                    public testing::WithParamInterface<bool> {
1739  public:
1740   ShelfViewVisibleBoundsTest() : text_direction_change_(GetParam()) {}
1741
1742   void CheckAllItemsAreInBounds() {
1743     gfx::Rect visible_bounds = shelf_view_->GetVisibleItemsBoundsInScreen();
1744     gfx::Rect shelf_bounds = shelf_view_->GetBoundsInScreen();
1745     EXPECT_TRUE(shelf_bounds.Contains(visible_bounds));
1746     for (int i = 0; i < test_api_->GetButtonCount(); ++i)
1747       if (internal::ShelfButton* button = test_api_->GetButton(i))
1748         EXPECT_TRUE(visible_bounds.Contains(button->GetBoundsInScreen()));
1749     CheckAppListButtonIsInBounds();
1750   }
1751
1752   void CheckAppListButtonIsInBounds() {
1753     gfx::Rect visible_bounds = shelf_view_->GetVisibleItemsBoundsInScreen();
1754     gfx::Rect app_list_button_bounds = shelf_view_->GetAppListButtonView()->
1755        GetBoundsInScreen();
1756     EXPECT_TRUE(visible_bounds.Contains(app_list_button_bounds));
1757   }
1758
1759  private:
1760   ScopedTextDirectionChange text_direction_change_;
1761
1762   DISALLOW_COPY_AND_ASSIGN(ShelfViewVisibleBoundsTest);
1763 };
1764
1765 TEST_P(ShelfViewVisibleBoundsTest, ItemsAreInBounds) {
1766   // Adding elements leaving some empty space.
1767   for (int i = 0; i < 3; i++) {
1768     AddAppShortcut();
1769   }
1770   test_api_->RunMessageLoopUntilAnimationsDone();
1771   EXPECT_FALSE(test_api_->IsOverflowButtonVisible());
1772   CheckAllItemsAreInBounds();
1773   // Same for overflow case.
1774   while (!test_api_->IsOverflowButtonVisible()) {
1775     AddAppShortcut();
1776   }
1777   test_api_->RunMessageLoopUntilAnimationsDone();
1778   CheckAllItemsAreInBounds();
1779 }
1780
1781 INSTANTIATE_TEST_CASE_P(LtrRtl, ShelfViewTextDirectionTest, testing::Bool());
1782 INSTANTIATE_TEST_CASE_P(VisibleBounds, ShelfViewVisibleBoundsTest,
1783     testing::Bool());
1784
1785 }  // namespace test
1786 }  // namespace ash