Introduce about flags for chrome hosted mode
[chromium-blink-merge.git] / ash / shelf / shelf_view_unittest.cc
blob6526fed776f6730b78b0217229e060b7d1130d98
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.
5 #include "ash/shelf/shelf_view.h"
7 #include <algorithm>
8 #include <utility>
9 #include <vector>
11 #include "ash/root_window_controller.h"
12 #include "ash/shelf/app_list_button.h"
13 #include "ash/shelf/overflow_bubble.h"
14 #include "ash/shelf/overflow_bubble_view.h"
15 #include "ash/shelf/shelf.h"
16 #include "ash/shelf/shelf_button.h"
17 #include "ash/shelf/shelf_constants.h"
18 #include "ash/shelf/shelf_icon_observer.h"
19 #include "ash/shelf/shelf_item_delegate_manager.h"
20 #include "ash/shelf/shelf_layout_manager.h"
21 #include "ash/shelf/shelf_model.h"
22 #include "ash/shelf/shelf_tooltip_manager.h"
23 #include "ash/shelf/shelf_widget.h"
24 #include "ash/shell.h"
25 #include "ash/shell_window_ids.h"
26 #include "ash/test/ash_test_base.h"
27 #include "ash/test/overflow_bubble_view_test_api.h"
28 #include "ash/test/shelf_test_api.h"
29 #include "ash/test/shelf_view_test_api.h"
30 #include "ash/test/shell_test_api.h"
31 #include "ash/test/test_shelf_delegate.h"
32 #include "ash/test/test_shelf_item_delegate.h"
33 #include "base/basictypes.h"
34 #include "base/compiler_specific.h"
35 #include "base/memory/scoped_ptr.h"
36 #include "base/strings/string_number_conversions.h"
37 #include "base/test/user_action_tester.h"
38 #include "base/time/time.h"
39 #include "ui/aura/test/aura_test_base.h"
40 #include "ui/aura/window.h"
41 #include "ui/aura/window_event_dispatcher.h"
42 #include "ui/base/l10n/l10n_util.h"
43 #include "ui/compositor/layer.h"
44 #include "ui/events/event.h"
45 #include "ui/events/event_constants.h"
46 #include "ui/events/event_utils.h"
47 #include "ui/events/test/event_generator.h"
48 #include "ui/gfx/geometry/point.h"
49 #include "ui/views/view_model.h"
50 #include "ui/views/widget/widget.h"
51 #include "ui/views/widget/widget_delegate.h"
52 #include "ui/wm/core/coordinate_conversion.h"
54 namespace ash {
55 namespace test {
57 ////////////////////////////////////////////////////////////////////////////////
58 // ShelfIconObserver tests.
60 class TestShelfIconObserver : public ShelfIconObserver {
61 public:
62 explicit TestShelfIconObserver(Shelf* shelf)
63 : shelf_(shelf),
64 change_notified_(false) {
65 if (shelf_)
66 shelf_->AddIconObserver(this);
69 ~TestShelfIconObserver() override {
70 if (shelf_)
71 shelf_->RemoveIconObserver(this);
74 // ShelfIconObserver implementation.
75 void OnShelfIconPositionsChanged() override { change_notified_ = true; }
77 int change_notified() const { return change_notified_; }
78 void Reset() { change_notified_ = false; }
80 private:
81 Shelf* shelf_;
82 bool change_notified_;
84 DISALLOW_COPY_AND_ASSIGN(TestShelfIconObserver);
87 class ShelfViewIconObserverTest : public AshTestBase {
88 public:
89 ShelfViewIconObserverTest() {}
90 ~ShelfViewIconObserverTest() override {}
92 void SetUp() override {
93 AshTestBase::SetUp();
94 Shelf* shelf = Shelf::ForPrimaryDisplay();
95 observer_.reset(new TestShelfIconObserver(shelf));
97 shelf_view_test_.reset(
98 new ShelfViewTestAPI(ShelfTestAPI(shelf).shelf_view()));
99 shelf_view_test_->SetAnimationDuration(1);
102 void TearDown() override {
103 observer_.reset();
104 AshTestBase::TearDown();
107 TestShelfIconObserver* observer() { return observer_.get(); }
109 ShelfViewTestAPI* shelf_view_test() {
110 return shelf_view_test_.get();
113 Shelf* ShelfForSecondaryDisplay() {
114 return Shelf::ForWindow(Shell::GetAllRootWindows()[1]);
117 private:
118 scoped_ptr<TestShelfIconObserver> observer_;
119 scoped_ptr<ShelfViewTestAPI> shelf_view_test_;
121 DISALLOW_COPY_AND_ASSIGN(ShelfViewIconObserverTest);
124 // TestShelfItemDelegate which tracks whether it gets selected.
125 class ShelfItemSelectionTracker : public TestShelfItemDelegate {
126 public:
127 ShelfItemSelectionTracker()
128 : TestShelfItemDelegate(NULL),
129 selected_(false),
130 item_selected_action_(kNoAction) {}
132 ~ShelfItemSelectionTracker() override {}
134 // Resets to the initial state.
135 void Reset() { selected_ = false; }
137 void set_item_selected_action(
138 ShelfItemDelegate::PerformedAction item_selected_action) {
139 item_selected_action_ = item_selected_action;
142 // Returns true if the delegate was selected.
143 bool WasSelected() {
144 return selected_;
147 // TestShelfItemDelegate:
148 ShelfItemDelegate::PerformedAction ItemSelected(
149 const ui::Event& event) override {
150 selected_ = true;
151 return item_selected_action_;
154 private:
155 bool selected_;
157 // The action returned from ItemSelected(const ui::Event&).
158 ShelfItemDelegate::PerformedAction item_selected_action_;
160 DISALLOW_COPY_AND_ASSIGN(ShelfItemSelectionTracker);
163 TEST_F(ShelfViewIconObserverTest, AddRemove) {
164 TestShelfDelegate* shelf_delegate = TestShelfDelegate::instance();
165 ASSERT_TRUE(shelf_delegate);
167 views::Widget::InitParams params(views::Widget::InitParams::TYPE_WINDOW);
168 params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
169 params.bounds = gfx::Rect(0, 0, 200, 200);
170 params.context = CurrentContext();
172 scoped_ptr<views::Widget> widget(new views::Widget());
173 widget->Init(params);
174 shelf_delegate->AddShelfItem(widget->GetNativeWindow());
175 shelf_view_test()->RunMessageLoopUntilAnimationsDone();
176 EXPECT_TRUE(observer()->change_notified());
177 observer()->Reset();
179 widget->Show();
180 widget->GetNativeWindow()->parent()->RemoveChild(widget->GetNativeWindow());
181 shelf_view_test()->RunMessageLoopUntilAnimationsDone();
182 EXPECT_TRUE(observer()->change_notified());
183 observer()->Reset();
186 // Sometimes fails on trybots on win7_aura. http://crbug.com/177135
187 #if defined(OS_WIN)
188 #define MAYBE_AddRemoveWithMultipleDisplays \
189 DISABLED_AddRemoveWithMultipleDisplays
190 #else
191 #define MAYBE_AddRemoveWithMultipleDisplays \
192 AddRemoveWithMultipleDisplays
193 #endif
194 // Make sure creating/deleting an window on one displays notifies a
195 // shelf on external display as well as one on primary.
196 TEST_F(ShelfViewIconObserverTest, MAYBE_AddRemoveWithMultipleDisplays) {
197 UpdateDisplay("400x400,400x400");
198 TestShelfIconObserver second_observer(ShelfForSecondaryDisplay());
200 TestShelfDelegate* shelf_delegate = TestShelfDelegate::instance();
201 ASSERT_TRUE(shelf_delegate);
203 views::Widget::InitParams params(views::Widget::InitParams::TYPE_WINDOW);
204 params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
205 params.bounds = gfx::Rect(0, 0, 200, 200);
206 params.context = CurrentContext();
208 scoped_ptr<views::Widget> widget(new views::Widget());
209 widget->Init(params);
210 shelf_delegate->AddShelfItem(widget->GetNativeWindow());
211 shelf_view_test()->RunMessageLoopUntilAnimationsDone();
212 EXPECT_TRUE(observer()->change_notified());
213 EXPECT_TRUE(second_observer.change_notified());
214 observer()->Reset();
215 second_observer.Reset();
217 widget->GetNativeWindow()->parent()->RemoveChild(widget->GetNativeWindow());
218 shelf_view_test()->RunMessageLoopUntilAnimationsDone();
219 EXPECT_TRUE(observer()->change_notified());
220 EXPECT_TRUE(second_observer.change_notified());
222 observer()->Reset();
223 second_observer.Reset();
226 TEST_F(ShelfViewIconObserverTest, BoundsChanged) {
227 ShelfWidget* widget = Shell::GetPrimaryRootWindowController()->shelf();
228 Shelf* shelf = Shelf::ForPrimaryDisplay();
229 gfx::Size shelf_size = widget->GetWindowBoundsInScreen().size();
230 shelf_size.set_width(shelf_size.width() / 2);
231 ASSERT_GT(shelf_size.width(), 0);
232 shelf->SetShelfViewBounds(gfx::Rect(shelf_size));
233 // No animation happens for ShelfView bounds change.
234 EXPECT_TRUE(observer()->change_notified());
235 observer()->Reset();
238 ////////////////////////////////////////////////////////////////////////////////
239 // ShelfView tests.
241 // A ShelfDelegate test double that will always convert between ShelfIDs and app
242 // ids. This does not support pinning and unpinning operations however CanPin()
243 // will return true and the return value of IsAppPinned(...) is configurable.
244 class TestShelfDelegateForShelfView : public ShelfDelegate {
245 public:
246 explicit TestShelfDelegateForShelfView(ShelfModel* model)
247 : model_(model) {}
248 ~TestShelfDelegateForShelfView() override {}
250 void set_is_app_pinned(bool is_pinned) { is_app_pinned_ = is_pinned; }
252 // ShelfDelegate overrides:
253 void OnShelfCreated(Shelf* shelf) override {}
255 void OnShelfDestroyed(Shelf* shelf) override {}
257 ShelfID GetShelfIDForAppID(const std::string& app_id) override {
258 ShelfID id = 0;
259 EXPECT_TRUE(base::StringToInt(app_id, &id));
260 return id;
263 bool HasShelfIDToAppIDMapping(ShelfID id) const override { return true; }
265 const std::string& GetAppIDForShelfID(ShelfID id) override {
266 // Use |app_id_| member variable because returning a reference to local
267 // variable is not allowed.
268 app_id_ = base::IntToString(id);
269 return app_id_;
272 void PinAppWithID(const std::string& app_id) override { NOTREACHED(); }
274 bool IsAppPinned(const std::string& app_id) override {
275 return is_app_pinned_;
278 bool CanPin() const override { return true; }
280 void UnpinAppWithID(const std::string& app_id) override { NOTREACHED(); }
282 private:
283 ShelfModel* model_;
285 // Tracks whether apps are pinned or not.
286 bool is_app_pinned_ = false;
288 // Temp member variable for returning a value. See the comment in the
289 // GetAppIDForShelfID().
290 std::string app_id_;
292 DISALLOW_COPY_AND_ASSIGN(TestShelfDelegateForShelfView);
295 class ShelfViewTest : public AshTestBase {
296 public:
297 ShelfViewTest()
298 : model_(NULL),
299 shelf_view_(NULL),
300 browser_index_(1),
301 item_manager_(NULL) {}
302 ~ShelfViewTest() override {}
304 void SetUp() override {
305 AshTestBase::SetUp();
306 test::ShellTestApi test_api(Shell::GetInstance());
307 model_ = test_api.shelf_model();
308 Shelf* shelf = Shelf::ForPrimaryDisplay();
309 shelf_view_ = ShelfTestAPI(shelf).shelf_view();
311 // The bounds should be big enough for 4 buttons + overflow chevron.
312 shelf_view_->SetBounds(0, 0, 500, kShelfSize);
314 test_api_.reset(new ShelfViewTestAPI(shelf_view_));
315 test_api_->SetAnimationDuration(1); // Speeds up animation for test.
317 ReplaceShelfDelegate();
319 item_manager_ = Shell::GetInstance()->shelf_item_delegate_manager();
320 DCHECK(item_manager_);
322 // Add browser shortcut shelf item at index 0 for test.
323 AddBrowserShortcut();
326 void TearDown() override {
327 shelf_delegate_ = nullptr;
328 test_api_.reset();
329 AshTestBase::TearDown();
332 protected:
333 void CreateAndSetShelfItemDelegateForID(ShelfID id) {
334 scoped_ptr<ShelfItemDelegate> delegate(new TestShelfItemDelegate(NULL));
335 item_manager_->SetShelfItemDelegate(id, delegate.Pass());
338 ShelfID AddBrowserShortcut() {
339 ShelfItem browser_shortcut;
340 browser_shortcut.type = TYPE_BROWSER_SHORTCUT;
342 ShelfID id = model_->next_id();
343 model_->AddAt(browser_index_, browser_shortcut);
344 CreateAndSetShelfItemDelegateForID(id);
345 test_api_->RunMessageLoopUntilAnimationsDone();
346 return id;
349 ShelfID AddAppShortcut() {
350 ShelfItem item;
351 item.type = TYPE_APP_SHORTCUT;
352 item.status = STATUS_CLOSED;
354 ShelfID id = model_->next_id();
355 model_->Add(item);
356 CreateAndSetShelfItemDelegateForID(id);
357 test_api_->RunMessageLoopUntilAnimationsDone();
358 return id;
361 ShelfID AddPanel() {
362 ShelfID id = AddPanelNoWait();
363 test_api_->RunMessageLoopUntilAnimationsDone();
364 return id;
367 ShelfID AddPlatformAppNoWait() {
368 ShelfItem item;
369 item.type = TYPE_PLATFORM_APP;
370 item.status = STATUS_RUNNING;
372 ShelfID id = model_->next_id();
373 model_->Add(item);
374 CreateAndSetShelfItemDelegateForID(id);
375 return id;
378 ShelfID AddPanelNoWait() {
379 ShelfItem item;
380 item.type = TYPE_APP_PANEL;
381 item.status = STATUS_RUNNING;
383 ShelfID id = model_->next_id();
384 model_->Add(item);
385 CreateAndSetShelfItemDelegateForID(id);
386 return id;
389 ShelfID AddPlatformApp() {
390 ShelfID id = AddPlatformAppNoWait();
391 test_api_->RunMessageLoopUntilAnimationsDone();
392 return id;
395 void RemoveByID(ShelfID id) {
396 model_->RemoveItemAt(model_->ItemIndexByID(id));
397 test_api_->RunMessageLoopUntilAnimationsDone();
400 ShelfButton* GetButtonByID(ShelfID id) {
401 int index = model_->ItemIndexByID(id);
402 return test_api_->GetButton(index);
405 ShelfItem GetItemByID(ShelfID id) {
406 ShelfItems::const_iterator items = model_->ItemByID(id);
407 return *items;
410 void CheckModelIDs(
411 const std::vector<std::pair<ShelfID, views::View*> >& id_map) {
412 size_t map_index = 0;
413 for (size_t model_index = 0;
414 model_index < model_->items().size();
415 ++model_index) {
416 ShelfItem item = model_->items()[model_index];
417 ShelfID id = item.id;
418 EXPECT_EQ(id_map[map_index].first, id);
419 EXPECT_EQ(id_map[map_index].second, GetButtonByID(id));
420 ++map_index;
422 ASSERT_EQ(map_index, id_map.size());
425 void VerifyShelfItemBoundsAreValid() {
426 for (int i = 0; i <= test_api_->GetLastVisibleIndex(); ++i) {
427 if (test_api_->GetButton(i)) {
428 gfx::Rect shelf_view_bounds = shelf_view_->GetLocalBounds();
429 gfx::Rect item_bounds = test_api_->GetBoundsByIndex(i);
430 EXPECT_GE(item_bounds.x(), 0);
431 EXPECT_GE(item_bounds.y(), 0);
432 EXPECT_LE(item_bounds.right(), shelf_view_bounds.width());
433 EXPECT_LE(item_bounds.bottom(), shelf_view_bounds.height());
438 ShelfButton* SimulateButtonPressed(ShelfButtonHost::Pointer pointer,
439 int button_index) {
440 ShelfButtonHost* button_host = shelf_view_;
441 ShelfButton* button = test_api_->GetButton(button_index);
442 ui::MouseEvent click_event(ui::ET_MOUSE_PRESSED, gfx::Point(),
443 button->GetBoundsInScreen().origin(),
444 ui::EventTimeForNow(), 0, 0);
445 button_host->PointerPressedOnButton(button, pointer, click_event);
446 return button;
449 // Simulates a single mouse click.
450 void SimulateClick(int button_index) {
451 ShelfButtonHost* button_host = shelf_view_;
452 ShelfButton* button =
453 SimulateButtonPressed(ShelfButtonHost::MOUSE, button_index);
454 ui::MouseEvent release_event(ui::ET_MOUSE_RELEASED, gfx::Point(),
455 button->GetBoundsInScreen().origin(),
456 ui::EventTimeForNow(), 0, 0);
457 test_api_->ButtonPressed(button, release_event);
458 button_host->PointerReleasedOnButton(button, ShelfButtonHost::MOUSE, false);
461 // Simulates the second click of a double click.
462 void SimulateDoubleClick(int button_index) {
463 ShelfButtonHost* button_host = shelf_view_;
464 ShelfButton* button =
465 SimulateButtonPressed(ShelfButtonHost::MOUSE, button_index);
466 ui::MouseEvent release_event(ui::ET_MOUSE_RELEASED, gfx::Point(),
467 button->GetBoundsInScreen().origin(),
468 ui::EventTimeForNow(), ui::EF_IS_DOUBLE_CLICK,
470 test_api_->ButtonPressed(button, release_event);
471 button_host->PointerReleasedOnButton(button, ShelfButtonHost::MOUSE, false);
474 views::View* SimulateDrag(ShelfButtonHost::Pointer pointer,
475 int button_index,
476 int destination_index) {
477 ShelfButtonHost* button_host = shelf_view_;
478 views::View* button = SimulateButtonPressed(pointer, button_index);
480 // Drag.
481 views::View* destination = test_api_->GetButton(destination_index);
482 ui::MouseEvent drag_event(
483 ui::ET_MOUSE_DRAGGED, gfx::Point(destination->x() - button->x(),
484 destination->y() - button->y()),
485 destination->GetBoundsInScreen().origin(), ui::EventTimeForNow(), 0, 0);
486 button_host->PointerDraggedOnButton(button, pointer, drag_event);
487 return button;
490 void SetupForDragTest(
491 std::vector<std::pair<ShelfID, views::View*> >* id_map) {
492 // Initialize |id_map| with the automatically-created shelf buttons.
493 for (size_t i = 0; i < model_->items().size(); ++i) {
494 ShelfButton* button = test_api_->GetButton(i);
495 id_map->push_back(std::make_pair(model_->items()[i].id, button));
497 ASSERT_NO_FATAL_FAILURE(CheckModelIDs(*id_map));
499 // Add 5 app shelf buttons for testing.
500 for (int i = 0; i < 5; ++i) {
501 ShelfID id = AddAppShortcut();
502 // App Icon is located at index 0, and browser shortcut is located at
503 // index 1. So we should start to add app shortcut at index 2.
504 id_map->insert(id_map->begin() + (i + browser_index_ + 1),
505 std::make_pair(id, GetButtonByID(id)));
507 ASSERT_NO_FATAL_FAILURE(CheckModelIDs(*id_map));
510 views::View* GetTooltipAnchorView() {
511 return shelf_view_->tooltip_manager()->anchor_;
514 void AddButtonsUntilOverflow() {
515 int items_added = 0;
516 while (!test_api_->IsOverflowButtonVisible()) {
517 AddAppShortcut();
518 ++items_added;
519 ASSERT_LT(items_added, 10000);
523 void ShowTooltip() {
524 shelf_view_->tooltip_manager()->ShowInternal();
527 void TestDraggingAnItemFromOverflowToShelf(bool cancel) {
528 test_api_->ShowOverflowBubble();
529 ASSERT_TRUE(test_api_->overflow_bubble() &&
530 test_api_->overflow_bubble()->IsShowing());
532 ash::test::ShelfViewTestAPI test_api_for_overflow(
533 test_api_->overflow_bubble()->shelf_view());
535 int total_item_count = model_->item_count();
537 int last_visible_item_id_in_shelf =
538 GetItemId(test_api_->GetLastVisibleIndex());
539 int second_last_visible_item_id_in_shelf =
540 GetItemId(test_api_->GetLastVisibleIndex() - 1);
541 int first_visible_item_id_in_overflow =
542 GetItemId(test_api_for_overflow.GetFirstVisibleIndex());
543 int second_last_visible_item_id_in_overflow =
544 GetItemId(test_api_for_overflow.GetLastVisibleIndex() - 1);
546 int drag_item_index =
547 test_api_for_overflow.GetLastVisibleIndex();
548 ShelfID drag_item_id = GetItemId(drag_item_index);
549 ShelfButton* drag_button = test_api_for_overflow.GetButton(drag_item_index);
550 gfx::Point center_point_of_drag_item =
551 drag_button->GetBoundsInScreen().CenterPoint();
553 ui::test::EventGenerator generator(ash::Shell::GetPrimaryRootWindow(),
554 center_point_of_drag_item);
555 // Rip an item off to OverflowBubble.
556 generator.PressLeftButton();
557 gfx::Point rip_off_point(center_point_of_drag_item.x(), 0);
558 generator.MoveMouseTo(rip_off_point);
559 test_api_for_overflow.RunMessageLoopUntilAnimationsDone();
560 ASSERT_TRUE(test_api_for_overflow.IsRippedOffFromShelf());
561 ASSERT_FALSE(test_api_for_overflow.DraggedItemFromOverflowToShelf());
563 // Move a dragged item into Shelf at |drop_index|.
564 int drop_index = 1;
565 gfx::Point drop_point =
566 test_api_->GetButton(drop_index)->GetBoundsInScreen().CenterPoint();
567 int item_width = test_api_for_overflow.GetButtonSize();
568 // To insert at |drop_index|, more smaller x-axis value of |drop_point|
569 // should be used.
570 gfx::Point modified_drop_point(drop_point.x() - item_width / 4,
571 drop_point.y());
572 generator.MoveMouseTo(modified_drop_point);
573 test_api_for_overflow.RunMessageLoopUntilAnimationsDone();
574 test_api_->RunMessageLoopUntilAnimationsDone();
575 ASSERT_TRUE(test_api_for_overflow.IsRippedOffFromShelf());
576 ASSERT_TRUE(test_api_for_overflow.DraggedItemFromOverflowToShelf());
578 if (cancel)
579 drag_button->OnMouseCaptureLost();
580 else
581 generator.ReleaseLeftButton();
583 test_api_for_overflow.RunMessageLoopUntilAnimationsDone();
584 test_api_->RunMessageLoopUntilAnimationsDone();
585 ASSERT_FALSE(test_api_for_overflow.IsRippedOffFromShelf());
586 ASSERT_FALSE(test_api_for_overflow.DraggedItemFromOverflowToShelf());
588 // Compare pre-stored items' id with newly positioned items' after dragging
589 // is canceled or finished.
590 if (cancel) {
591 EXPECT_EQ(last_visible_item_id_in_shelf,
592 GetItemId(test_api_->GetLastVisibleIndex()));
593 EXPECT_EQ(second_last_visible_item_id_in_shelf,
594 GetItemId(test_api_->GetLastVisibleIndex() - 1));
595 EXPECT_EQ(first_visible_item_id_in_overflow,
596 GetItemId(test_api_for_overflow.GetFirstVisibleIndex()));
597 EXPECT_EQ(second_last_visible_item_id_in_overflow,
598 GetItemId(test_api_for_overflow.GetLastVisibleIndex() - 1));
599 } else {
600 EXPECT_EQ(drag_item_id, GetItemId(drop_index));
601 EXPECT_EQ(total_item_count, model_->item_count());
602 EXPECT_EQ(last_visible_item_id_in_shelf,
603 GetItemId(test_api_for_overflow.GetFirstVisibleIndex()));
604 EXPECT_EQ(second_last_visible_item_id_in_shelf,
605 GetItemId(test_api_->GetLastVisibleIndex()));
606 EXPECT_EQ(first_visible_item_id_in_overflow,
607 GetItemId(test_api_for_overflow.GetFirstVisibleIndex() + 1));
608 EXPECT_EQ(second_last_visible_item_id_in_overflow,
609 GetItemId(test_api_for_overflow.GetLastVisibleIndex()));
613 // Returns the item's ShelfID at |index|.
614 ShelfID GetItemId(int index) {
615 DCHECK_GE(index, 0);
616 return model_->items()[index].id;
619 void ReplaceShelfDelegate() {
620 // Replace ShelfDelegate.
621 test::ShellTestApi shell_test_api(Shell::GetInstance());
622 shell_test_api.SetShelfDelegate(NULL);
623 shelf_delegate_ = new TestShelfDelegateForShelfView(model_);
624 shell_test_api.SetShelfDelegate(shelf_delegate_);
625 test::ShelfTestAPI(Shelf::ForPrimaryDisplay())
626 .SetShelfDelegate(shelf_delegate_);
627 test_api_->SetShelfDelegate(shelf_delegate_);
630 ShelfModel* model_;
631 ShelfView* shelf_view_;
632 int browser_index_;
633 ShelfItemDelegateManager* item_manager_;
635 // Owned by ash::Shell.
636 TestShelfDelegateForShelfView* shelf_delegate_;
638 scoped_ptr<ShelfViewTestAPI> test_api_;
640 private:
641 DISALLOW_COPY_AND_ASSIGN(ShelfViewTest);
644 class ScopedTextDirectionChange {
645 public:
646 explicit ScopedTextDirectionChange(bool is_rtl) : is_rtl_(is_rtl) {
647 original_locale_ = l10n_util::GetApplicationLocale(std::string());
648 if (is_rtl_)
649 base::i18n::SetICUDefaultLocale("he");
650 CheckTextDirectionIsCorrect();
653 ~ScopedTextDirectionChange() {
654 if (is_rtl_)
655 base::i18n::SetICUDefaultLocale(original_locale_);
658 private:
659 void CheckTextDirectionIsCorrect() {
660 ASSERT_EQ(is_rtl_, base::i18n::IsRTL());
663 bool is_rtl_;
664 std::string original_locale_;
667 class ShelfViewTextDirectionTest
668 : public ShelfViewTest,
669 public testing::WithParamInterface<bool> {
670 public:
671 ShelfViewTextDirectionTest() : text_direction_change_(GetParam()) {}
672 virtual ~ShelfViewTextDirectionTest() {}
674 void SetUp() override { ShelfViewTest::SetUp(); }
676 void TearDown() override { ShelfViewTest::TearDown(); }
678 private:
679 ScopedTextDirectionChange text_direction_change_;
681 DISALLOW_COPY_AND_ASSIGN(ShelfViewTextDirectionTest);
684 // Checks that the ideal item icon bounds match the view's bounds in the screen
685 // in both LTR and RTL.
686 TEST_P(ShelfViewTextDirectionTest, IdealBoundsOfItemIcon) {
687 ShelfID id = AddPlatformApp();
688 ShelfButton* button = GetButtonByID(id);
689 gfx::Rect item_bounds = button->GetBoundsInScreen();
690 gfx::Point icon_offset = button->GetIconBounds().origin();
691 item_bounds.Offset(icon_offset.OffsetFromOrigin());
692 gfx::Rect ideal_bounds = shelf_view_->GetIdealBoundsOfItemIcon(id);
693 gfx::Point screen_origin;
694 views::View::ConvertPointToScreen(shelf_view_, &screen_origin);
695 ideal_bounds.Offset(screen_origin.x(), screen_origin.y());
696 EXPECT_EQ(item_bounds.x(), ideal_bounds.x());
697 EXPECT_EQ(item_bounds.y(), ideal_bounds.y());
700 // Check that items in the overflow area are returning the overflow button as
701 // ideal bounds.
702 TEST_F(ShelfViewTest, OverflowButtonBounds) {
703 ShelfID first_id = AddPlatformApp();
704 ShelfID overflow_id = AddPlatformApp();
705 int items_added = 0;
706 while (!test_api_->IsOverflowButtonVisible()) {
707 // Added button is visible after animation while in this loop.
708 EXPECT_TRUE(GetButtonByID(overflow_id)->visible());
709 overflow_id = AddPlatformApp();
710 ++items_added;
711 ASSERT_LT(items_added, 10000);
713 ShelfID last_id = AddPlatformApp();
715 gfx::Rect first_bounds = shelf_view_->GetIdealBoundsOfItemIcon(first_id);
716 gfx::Rect overflow_bounds =
717 shelf_view_->GetIdealBoundsOfItemIcon(overflow_id);
718 gfx::Rect last_bounds = shelf_view_->GetIdealBoundsOfItemIcon(last_id);
720 // Check that all items have the same size and that the overflow items are
721 // identical whereas the first one does not match either of them.
722 EXPECT_EQ(first_bounds.size().ToString(), last_bounds.size().ToString());
723 EXPECT_NE(first_bounds.ToString(), last_bounds.ToString());
724 EXPECT_EQ(overflow_bounds.ToString(), last_bounds.ToString());
727 // Checks that shelf view contents are considered in the correct drag group.
728 TEST_F(ShelfViewTest, EnforceDragType) {
729 EXPECT_TRUE(test_api_->SameDragType(TYPE_PLATFORM_APP, TYPE_PLATFORM_APP));
730 EXPECT_FALSE(test_api_->SameDragType(TYPE_PLATFORM_APP, TYPE_APP_SHORTCUT));
731 EXPECT_FALSE(test_api_->SameDragType(TYPE_PLATFORM_APP,
732 TYPE_BROWSER_SHORTCUT));
733 EXPECT_FALSE(test_api_->SameDragType(TYPE_PLATFORM_APP, TYPE_WINDOWED_APP));
734 EXPECT_FALSE(test_api_->SameDragType(TYPE_PLATFORM_APP, TYPE_APP_LIST));
735 EXPECT_FALSE(test_api_->SameDragType(TYPE_PLATFORM_APP, TYPE_APP_PANEL));
737 EXPECT_TRUE(test_api_->SameDragType(TYPE_APP_SHORTCUT, TYPE_APP_SHORTCUT));
738 EXPECT_TRUE(test_api_->SameDragType(TYPE_APP_SHORTCUT,
739 TYPE_BROWSER_SHORTCUT));
740 EXPECT_FALSE(test_api_->SameDragType(TYPE_APP_SHORTCUT,
741 TYPE_WINDOWED_APP));
742 EXPECT_FALSE(test_api_->SameDragType(TYPE_APP_SHORTCUT, TYPE_APP_LIST));
743 EXPECT_FALSE(test_api_->SameDragType(TYPE_APP_SHORTCUT, TYPE_APP_PANEL));
745 EXPECT_TRUE(test_api_->SameDragType(TYPE_BROWSER_SHORTCUT,
746 TYPE_BROWSER_SHORTCUT));
747 EXPECT_FALSE(test_api_->SameDragType(TYPE_BROWSER_SHORTCUT,
748 TYPE_WINDOWED_APP));
749 EXPECT_FALSE(test_api_->SameDragType(TYPE_BROWSER_SHORTCUT, TYPE_APP_LIST));
750 EXPECT_FALSE(test_api_->SameDragType(TYPE_BROWSER_SHORTCUT, TYPE_APP_PANEL));
752 EXPECT_TRUE(test_api_->SameDragType(TYPE_WINDOWED_APP, TYPE_WINDOWED_APP));
753 EXPECT_FALSE(test_api_->SameDragType(TYPE_WINDOWED_APP, TYPE_APP_LIST));
754 EXPECT_FALSE(test_api_->SameDragType(TYPE_WINDOWED_APP, TYPE_APP_PANEL));
756 EXPECT_TRUE(test_api_->SameDragType(TYPE_APP_LIST, TYPE_APP_LIST));
757 EXPECT_FALSE(test_api_->SameDragType(TYPE_APP_LIST, TYPE_APP_PANEL));
759 EXPECT_TRUE(test_api_->SameDragType(TYPE_APP_PANEL, TYPE_APP_PANEL));
762 // Adds platform app button until overflow and verifies that the last added
763 // platform app button is hidden.
764 TEST_F(ShelfViewTest, AddBrowserUntilOverflow) {
765 // All buttons should be visible.
766 ASSERT_EQ(test_api_->GetButtonCount(),
767 test_api_->GetLastVisibleIndex() + 1);
769 // Add platform app button until overflow.
770 int items_added = 0;
771 ShelfID last_added = AddPlatformApp();
772 while (!test_api_->IsOverflowButtonVisible()) {
773 // Added button is visible after animation while in this loop.
774 EXPECT_TRUE(GetButtonByID(last_added)->visible());
776 last_added = AddPlatformApp();
777 ++items_added;
778 ASSERT_LT(items_added, 10000);
781 // The last added button should be invisible.
782 EXPECT_FALSE(GetButtonByID(last_added)->visible());
785 // Adds one platform app button then adds app shortcut until overflow. Verifies
786 // that the browser button gets hidden on overflow and last added app shortcut
787 // is still visible.
788 TEST_F(ShelfViewTest, AddAppShortcutWithBrowserButtonUntilOverflow) {
789 // All buttons should be visible.
790 ASSERT_EQ(test_api_->GetButtonCount(),
791 test_api_->GetLastVisibleIndex() + 1);
793 ShelfID browser_button_id = AddPlatformApp();
795 // Add app shortcut until overflow.
796 int items_added = 0;
797 ShelfID last_added = AddAppShortcut();
798 while (!test_api_->IsOverflowButtonVisible()) {
799 // Added button is visible after animation while in this loop.
800 EXPECT_TRUE(GetButtonByID(last_added)->visible());
802 last_added = AddAppShortcut();
803 ++items_added;
804 ASSERT_LT(items_added, 10000);
807 // And the platform app button is invisible.
808 EXPECT_FALSE(GetButtonByID(browser_button_id)->visible());
811 TEST_F(ShelfViewTest, AddPanelHidesPlatformAppButton) {
812 // All buttons should be visible.
813 ASSERT_EQ(test_api_->GetButtonCount(),
814 test_api_->GetLastVisibleIndex() + 1);
816 // Add platform app button until overflow, remember last visible platform app
817 // button.
818 int items_added = 0;
819 ShelfID first_added = AddPlatformApp();
820 EXPECT_TRUE(GetButtonByID(first_added)->visible());
821 while (true) {
822 ShelfID added = AddPlatformApp();
823 if (test_api_->IsOverflowButtonVisible()) {
824 EXPECT_FALSE(GetButtonByID(added)->visible());
825 RemoveByID(added);
826 break;
828 ++items_added;
829 ASSERT_LT(items_added, 10000);
832 ShelfID panel = AddPanel();
833 EXPECT_TRUE(test_api_->IsOverflowButtonVisible());
835 RemoveByID(panel);
836 EXPECT_FALSE(test_api_->IsOverflowButtonVisible());
839 // When there are more panels then platform app buttons we should hide panels
840 // rather than platform apps.
841 TEST_F(ShelfViewTest, PlatformAppHidesExcessPanels) {
842 // All buttons should be visible.
843 ASSERT_EQ(test_api_->GetButtonCount(),
844 test_api_->GetLastVisibleIndex() + 1);
846 // Add platform app button.
847 ShelfID platform_app = AddPlatformApp();
848 ShelfID first_panel = AddPanel();
850 EXPECT_TRUE(GetButtonByID(platform_app)->visible());
851 EXPECT_TRUE(GetButtonByID(first_panel)->visible());
853 // Add panels until there is an overflow.
854 ShelfID last_panel = first_panel;
855 int items_added = 0;
856 while (!test_api_->IsOverflowButtonVisible()) {
857 last_panel = AddPanel();
858 ++items_added;
859 ASSERT_LT(items_added, 10000);
862 // The first panel should now be hidden by the new platform apps needing
863 // space.
864 EXPECT_FALSE(GetButtonByID(first_panel)->visible());
865 EXPECT_TRUE(GetButtonByID(last_panel)->visible());
866 EXPECT_TRUE(GetButtonByID(platform_app)->visible());
868 // Adding platform apps should eventually begin to hide platform apps. We will
869 // add platform apps until either the last panel or platform app is hidden.
870 items_added = 0;
871 while (GetButtonByID(platform_app)->visible() &&
872 GetButtonByID(last_panel)->visible()) {
873 platform_app = AddPlatformApp();
874 ++items_added;
875 ASSERT_LT(items_added, 10000);
877 EXPECT_TRUE(GetButtonByID(last_panel)->visible());
878 EXPECT_FALSE(GetButtonByID(platform_app)->visible());
881 // Making sure that no buttons on the shelf will ever overlap after adding many
882 // of them.
883 TEST_F(ShelfViewTest, AssertNoButtonsOverlap) {
884 std::vector<ShelfID> button_ids;
885 // Add app icons until the overflow button is visible.
886 while (!test_api_->IsOverflowButtonVisible()) {
887 ShelfID id = AddPlatformApp();
888 button_ids.push_back(id);
890 ASSERT_LT(button_ids.size(), 10000U);
891 ASSERT_GT(button_ids.size(), 2U);
893 // Remove 2 icons to make more room for panel icons, the overflow button
894 // should go away.
895 for (int i = 0; i < 2; ++i) {
896 ShelfID id = button_ids.back();
897 RemoveByID(id);
898 button_ids.pop_back();
900 EXPECT_FALSE(test_api_->IsOverflowButtonVisible());
901 EXPECT_TRUE(GetButtonByID(button_ids.back())->visible());
903 // Add 20 panel icons, and expect to have overflow.
904 for (int i = 0; i < 20; ++i) {
905 ShelfID id = AddPanel();
906 button_ids.push_back(id);
908 ASSERT_LT(button_ids.size(), 10000U);
909 EXPECT_TRUE(test_api_->IsOverflowButtonVisible());
911 // Test that any two successive visible icons never overlap in all shelf
912 // alignment types.
913 const ShelfAlignment kAlignments[] = {
914 SHELF_ALIGNMENT_LEFT,
915 SHELF_ALIGNMENT_RIGHT,
916 SHELF_ALIGNMENT_TOP,
917 SHELF_ALIGNMENT_BOTTOM
920 for (ShelfAlignment alignment : kAlignments) {
921 EXPECT_TRUE(shelf_view_->shelf_layout_manager()->SetAlignment(alignment));
922 // For every 2 successive visible icons, expect that their bounds don't
923 // intersect.
924 for (int i = 1; i < test_api_->GetButtonCount() - 1; ++i) {
925 if (!(test_api_->GetButton(i)->visible() &&
926 test_api_->GetButton(i + 1)->visible())) {
927 continue;
930 const gfx::Rect& bounds1 = test_api_->GetBoundsByIndex(i);
931 const gfx::Rect& bounds2 = test_api_->GetBoundsByIndex(i + 1);
932 EXPECT_FALSE(bounds1.Intersects(bounds2));
937 // Adds button until overflow then removes first added one. Verifies that
938 // the last added one changes from invisible to visible and overflow
939 // chevron is gone.
940 TEST_F(ShelfViewTest, RemoveButtonRevealsOverflowed) {
941 // All buttons should be visible.
942 ASSERT_EQ(test_api_->GetButtonCount(),
943 test_api_->GetLastVisibleIndex() + 1);
945 // Add platform app buttons until overflow.
946 int items_added = 0;
947 ShelfID first_added = AddPlatformApp();
948 ShelfID last_added = first_added;
949 while (!test_api_->IsOverflowButtonVisible()) {
950 last_added = AddPlatformApp();
951 ++items_added;
952 ASSERT_LT(items_added, 10000);
955 // Expect add more than 1 button. First added is visible and last is not.
956 EXPECT_NE(first_added, last_added);
957 EXPECT_TRUE(GetButtonByID(first_added)->visible());
958 EXPECT_FALSE(GetButtonByID(last_added)->visible());
960 // Remove first added.
961 RemoveByID(first_added);
963 // Last added button becomes visible and overflow chevron is gone.
964 EXPECT_TRUE(GetButtonByID(last_added)->visible());
965 EXPECT_EQ(1.0f, GetButtonByID(last_added)->layer()->opacity());
966 EXPECT_FALSE(test_api_->IsOverflowButtonVisible());
969 // Verifies that remove last overflowed button should hide overflow chevron.
970 TEST_F(ShelfViewTest, RemoveLastOverflowed) {
971 // All buttons should be visible.
972 ASSERT_EQ(test_api_->GetButtonCount(),
973 test_api_->GetLastVisibleIndex() + 1);
975 // Add platform app button until overflow.
976 int items_added = 0;
977 ShelfID last_added = AddPlatformApp();
978 while (!test_api_->IsOverflowButtonVisible()) {
979 last_added = AddPlatformApp();
980 ++items_added;
981 ASSERT_LT(items_added, 10000);
984 RemoveByID(last_added);
985 EXPECT_FALSE(test_api_->IsOverflowButtonVisible());
988 // Adds platform app button without waiting for animation to finish and verifies
989 // that all added buttons are visible.
990 TEST_F(ShelfViewTest, AddButtonQuickly) {
991 // All buttons should be visible.
992 ASSERT_EQ(test_api_->GetButtonCount(),
993 test_api_->GetLastVisibleIndex() + 1);
995 // Add a few platform buttons quickly without wait for animation.
996 int added_count = 0;
997 while (!test_api_->IsOverflowButtonVisible()) {
998 AddPlatformAppNoWait();
999 ++added_count;
1000 ASSERT_LT(added_count, 10000);
1003 // ShelfView should be big enough to hold at least 3 new buttons.
1004 ASSERT_GE(added_count, 3);
1006 // Wait for the last animation to finish.
1007 test_api_->RunMessageLoopUntilAnimationsDone();
1009 // Verifies non-overflow buttons are visible.
1010 for (int i = 0; i <= test_api_->GetLastVisibleIndex(); ++i) {
1011 ShelfButton* button = test_api_->GetButton(i);
1012 if (button) {
1013 EXPECT_TRUE(button->visible()) << "button index=" << i;
1014 EXPECT_EQ(1.0f, button->layer()->opacity()) << "button index=" << i;
1019 // Check that model changes are handled correctly while a shelf icon is being
1020 // dragged.
1021 TEST_F(ShelfViewTest, ModelChangesWhileDragging) {
1022 ShelfButtonHost* button_host = shelf_view_;
1024 std::vector<std::pair<ShelfID, views::View*> > id_map;
1025 SetupForDragTest(&id_map);
1027 // Dragging browser shortcut at index 1.
1028 EXPECT_TRUE(model_->items()[1].type == TYPE_BROWSER_SHORTCUT);
1029 views::View* dragged_button = SimulateDrag(ShelfButtonHost::MOUSE, 1, 3);
1030 std::rotate(id_map.begin() + 1,
1031 id_map.begin() + 2,
1032 id_map.begin() + 4);
1033 ASSERT_NO_FATAL_FAILURE(CheckModelIDs(id_map));
1034 button_host->PointerReleasedOnButton(
1035 dragged_button, ShelfButtonHost::MOUSE, false);
1036 EXPECT_TRUE(model_->items()[3].type == TYPE_BROWSER_SHORTCUT);
1038 // Dragging changes model order.
1039 dragged_button = SimulateDrag(ShelfButtonHost::MOUSE, 1, 3);
1040 std::rotate(id_map.begin() + 1,
1041 id_map.begin() + 2,
1042 id_map.begin() + 4);
1043 ASSERT_NO_FATAL_FAILURE(CheckModelIDs(id_map));
1045 // Cancelling the drag operation restores previous order.
1046 button_host->PointerReleasedOnButton(
1047 dragged_button, ShelfButtonHost::MOUSE, true);
1048 std::rotate(id_map.begin() + 1,
1049 id_map.begin() + 3,
1050 id_map.begin() + 4);
1051 ASSERT_NO_FATAL_FAILURE(CheckModelIDs(id_map));
1053 // Deleting an item keeps the remaining intact.
1054 dragged_button = SimulateDrag(ShelfButtonHost::MOUSE, 1, 3);
1055 model_->RemoveItemAt(1);
1056 id_map.erase(id_map.begin() + 1);
1057 ASSERT_NO_FATAL_FAILURE(CheckModelIDs(id_map));
1058 button_host->PointerReleasedOnButton(
1059 dragged_button, ShelfButtonHost::MOUSE, false);
1061 // Adding a shelf item cancels the drag and respects the order.
1062 dragged_button = SimulateDrag(ShelfButtonHost::MOUSE, 1, 3);
1063 ShelfID new_id = AddAppShortcut();
1064 id_map.insert(id_map.begin() + 6,
1065 std::make_pair(new_id, GetButtonByID(new_id)));
1066 ASSERT_NO_FATAL_FAILURE(CheckModelIDs(id_map));
1067 button_host->PointerReleasedOnButton(
1068 dragged_button, ShelfButtonHost::MOUSE, false);
1070 // Adding a shelf item at the end (i.e. a panel) canels drag and respects
1071 // the order.
1072 dragged_button = SimulateDrag(ShelfButtonHost::MOUSE, 1, 3);
1073 new_id = AddPanel();
1074 id_map.insert(id_map.begin() + 7,
1075 std::make_pair(new_id, GetButtonByID(new_id)));
1076 ASSERT_NO_FATAL_FAILURE(CheckModelIDs(id_map));
1077 button_host->PointerReleasedOnButton(
1078 dragged_button, ShelfButtonHost::MOUSE, false);
1081 // Check that 2nd drag from the other pointer would be ignored.
1082 TEST_F(ShelfViewTest, SimultaneousDrag) {
1083 ShelfButtonHost* button_host = shelf_view_;
1085 std::vector<std::pair<ShelfID, views::View*> > id_map;
1086 SetupForDragTest(&id_map);
1088 // Start a mouse drag.
1089 views::View* dragged_button_mouse =
1090 SimulateDrag(ShelfButtonHost::MOUSE, 1, 3);
1091 std::rotate(id_map.begin() + 1,
1092 id_map.begin() + 2,
1093 id_map.begin() + 4);
1094 ASSERT_NO_FATAL_FAILURE(CheckModelIDs(id_map));
1095 // Attempt a touch drag before the mouse drag finishes.
1096 views::View* dragged_button_touch =
1097 SimulateDrag(ShelfButtonHost::TOUCH, 4, 2);
1099 // Nothing changes since 2nd drag is ignored.
1100 ASSERT_NO_FATAL_FAILURE(CheckModelIDs(id_map));
1102 // Finish the mouse drag.
1103 button_host->PointerReleasedOnButton(
1104 dragged_button_mouse, ShelfButtonHost::MOUSE, false);
1105 ASSERT_NO_FATAL_FAILURE(CheckModelIDs(id_map));
1107 // Now start a touch drag.
1108 dragged_button_touch = SimulateDrag(ShelfButtonHost::TOUCH, 4, 2);
1109 std::rotate(id_map.begin() + 3,
1110 id_map.begin() + 4,
1111 id_map.begin() + 5);
1112 ASSERT_NO_FATAL_FAILURE(CheckModelIDs(id_map));
1114 // And attempt a mouse drag before the touch drag finishes.
1115 dragged_button_mouse = SimulateDrag(ShelfButtonHost::MOUSE, 1, 2);
1117 // Nothing changes since 2nd drag is ignored.
1118 ASSERT_NO_FATAL_FAILURE(CheckModelIDs(id_map));
1120 button_host->PointerReleasedOnButton(
1121 dragged_button_touch, ShelfButtonHost::TOUCH, false);
1122 ASSERT_NO_FATAL_FAILURE(CheckModelIDs(id_map));
1125 // Check that clicking first on one item and then dragging another works as
1126 // expected.
1127 TEST_F(ShelfViewTest, ClickOneDragAnother) {
1128 ShelfButtonHost* button_host = shelf_view_;
1130 std::vector<std::pair<ShelfID, views::View*> > id_map;
1131 SetupForDragTest(&id_map);
1133 // A click on item 1 is simulated.
1134 SimulateClick(1);
1136 // Dragging browser index at 0 should change the model order correctly.
1137 EXPECT_TRUE(model_->items()[1].type == TYPE_BROWSER_SHORTCUT);
1138 views::View* dragged_button = SimulateDrag(ShelfButtonHost::MOUSE, 1, 3);
1139 std::rotate(id_map.begin() + 1,
1140 id_map.begin() + 2,
1141 id_map.begin() + 4);
1142 ASSERT_NO_FATAL_FAILURE(CheckModelIDs(id_map));
1143 button_host->PointerReleasedOnButton(
1144 dragged_button, ShelfButtonHost::MOUSE, false);
1145 EXPECT_TRUE(model_->items()[3].type == TYPE_BROWSER_SHORTCUT);
1148 // Tests that double-clicking an item does not activate it twice.
1149 TEST_F(ShelfViewTest, ClickingTwiceActivatesOnce) {
1150 // Watch for selection of the browser shortcut.
1151 ShelfID browser_shelf_id = model_->items()[browser_index_].id;
1152 ShelfItemSelectionTracker* selection_tracker = new ShelfItemSelectionTracker;
1153 item_manager_->SetShelfItemDelegate(
1154 browser_shelf_id,
1155 scoped_ptr<ShelfItemDelegate>(selection_tracker).Pass());
1157 // A single click selects the item.
1158 SimulateClick(browser_index_);
1159 EXPECT_TRUE(selection_tracker->WasSelected());
1161 // A double-click does not select the item.
1162 selection_tracker->Reset();
1163 SimulateDoubleClick(browser_index_);
1164 EXPECT_FALSE(selection_tracker->WasSelected());
1167 // Check that clicking an item and jittering the mouse a bit still selects the
1168 // item.
1169 TEST_F(ShelfViewTest, ClickAndMoveSlightly) {
1170 std::vector<std::pair<ShelfID, views::View*> > id_map;
1171 SetupForDragTest(&id_map);
1173 ShelfID shelf_id = (id_map.begin() + 1)->first;
1174 views::View* button = (id_map.begin() + 1)->second;
1176 // Replace the ShelfItemDelegate for |shelf_id| with one which tracks whether
1177 // the shelf item gets selected.
1178 ShelfItemSelectionTracker* selection_tracker = new ShelfItemSelectionTracker;
1179 item_manager_->SetShelfItemDelegate(
1180 shelf_id,
1181 scoped_ptr<ShelfItemDelegate>(selection_tracker).Pass());
1183 gfx::Vector2d press_offset(5, 30);
1184 gfx::Point press_location = gfx::Point() + press_offset;
1185 gfx::Point press_location_in_screen =
1186 button->GetBoundsInScreen().origin() + press_offset;
1188 ui::MouseEvent click_event(ui::ET_MOUSE_PRESSED, press_location,
1189 press_location_in_screen, ui::EventTimeForNow(),
1190 ui::EF_LEFT_MOUSE_BUTTON, 0);
1191 button->OnMousePressed(click_event);
1193 ui::MouseEvent drag_event1(
1194 ui::ET_MOUSE_DRAGGED, press_location + gfx::Vector2d(0, 1),
1195 press_location_in_screen + gfx::Vector2d(0, 1), ui::EventTimeForNow(),
1196 ui::EF_LEFT_MOUSE_BUTTON, 0);
1197 button->OnMouseDragged(drag_event1);
1199 ui::MouseEvent drag_event2(
1200 ui::ET_MOUSE_DRAGGED, press_location + gfx::Vector2d(-1, 0),
1201 press_location_in_screen + gfx::Vector2d(-1, 0), ui::EventTimeForNow(),
1202 ui::EF_LEFT_MOUSE_BUTTON, 0);
1203 button->OnMouseDragged(drag_event2);
1205 ui::MouseEvent release_event(
1206 ui::ET_MOUSE_RELEASED, press_location + gfx::Vector2d(-1, 0),
1207 press_location_in_screen + gfx::Vector2d(-1, 0), ui::EventTimeForNow(),
1208 ui::EF_LEFT_MOUSE_BUTTON, 0);
1209 button->OnMouseReleased(release_event);
1211 EXPECT_TRUE(selection_tracker->WasSelected());
1214 // Confirm that item status changes are reflected in the buttons.
1215 TEST_F(ShelfViewTest, ShelfItemStatus) {
1216 // All buttons should be visible.
1217 ASSERT_EQ(test_api_->GetButtonCount(),
1218 test_api_->GetLastVisibleIndex() + 1);
1220 // Add platform app button.
1221 ShelfID last_added = AddPlatformApp();
1222 ShelfItem item = GetItemByID(last_added);
1223 int index = model_->ItemIndexByID(last_added);
1224 ShelfButton* button = GetButtonByID(last_added);
1225 ASSERT_EQ(ShelfButton::STATE_RUNNING, button->state());
1226 item.status = STATUS_ACTIVE;
1227 model_->Set(index, item);
1228 ASSERT_EQ(ShelfButton::STATE_ACTIVE, button->state());
1229 item.status = STATUS_ATTENTION;
1230 model_->Set(index, item);
1231 ASSERT_EQ(ShelfButton::STATE_ATTENTION, button->state());
1234 // Confirm that item status changes are reflected in the buttons
1235 // for platform apps.
1236 TEST_F(ShelfViewTest, ShelfItemStatusPlatformApp) {
1237 // All buttons should be visible.
1238 ASSERT_EQ(test_api_->GetButtonCount(),
1239 test_api_->GetLastVisibleIndex() + 1);
1241 // Add platform app button.
1242 ShelfID last_added = AddPlatformApp();
1243 ShelfItem item = GetItemByID(last_added);
1244 int index = model_->ItemIndexByID(last_added);
1245 ShelfButton* button = GetButtonByID(last_added);
1246 ASSERT_EQ(ShelfButton::STATE_RUNNING, button->state());
1247 item.status = STATUS_ACTIVE;
1248 model_->Set(index, item);
1249 ASSERT_EQ(ShelfButton::STATE_ACTIVE, button->state());
1250 item.status = STATUS_ATTENTION;
1251 model_->Set(index, item);
1252 ASSERT_EQ(ShelfButton::STATE_ATTENTION, button->state());
1255 // Confirm that shelf item bounds are correctly updated on shelf changes.
1256 TEST_F(ShelfViewTest, ShelfItemBoundsCheck) {
1257 VerifyShelfItemBoundsAreValid();
1258 shelf_view_->shelf_layout_manager()->SetAutoHideBehavior(
1259 SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS);
1260 test_api_->RunMessageLoopUntilAnimationsDone();
1261 VerifyShelfItemBoundsAreValid();
1262 shelf_view_->shelf_layout_manager()->SetAutoHideBehavior(
1263 SHELF_AUTO_HIDE_BEHAVIOR_NEVER);
1264 test_api_->RunMessageLoopUntilAnimationsDone();
1265 VerifyShelfItemBoundsAreValid();
1268 TEST_F(ShelfViewTest, ShelfTooltipTest) {
1269 ASSERT_EQ(test_api_->GetLastVisibleIndex() + 1,
1270 test_api_->GetButtonCount());
1272 // Prepare some items to the shelf.
1273 ShelfID app_button_id = AddAppShortcut();
1274 ShelfID platform_button_id = AddPlatformApp();
1276 ShelfButton* app_button = GetButtonByID(app_button_id);
1277 ShelfButton* platform_button = GetButtonByID(platform_button_id);
1279 ShelfButtonHost* button_host = shelf_view_;
1280 ShelfTooltipManager* tooltip_manager = shelf_view_->tooltip_manager();
1282 button_host->MouseEnteredButton(app_button);
1283 // There's a delay to show the tooltip, so it's not visible yet.
1284 EXPECT_FALSE(tooltip_manager->IsVisible());
1285 EXPECT_EQ(app_button, GetTooltipAnchorView());
1287 ShowTooltip();
1288 EXPECT_TRUE(tooltip_manager->IsVisible());
1290 // Once it's visible, it keeps visibility and is pointing to the same
1291 // item.
1292 button_host->MouseExitedButton(app_button);
1293 EXPECT_TRUE(tooltip_manager->IsVisible());
1294 EXPECT_EQ(app_button, GetTooltipAnchorView());
1296 // When entered to another item, it switches to the new item. There is no
1297 // delay for the visibility.
1298 button_host->MouseEnteredButton(platform_button);
1299 EXPECT_TRUE(tooltip_manager->IsVisible());
1300 EXPECT_EQ(platform_button, GetTooltipAnchorView());
1302 button_host->MouseExitedButton(platform_button);
1303 tooltip_manager->Close();
1305 // Next time: enter app_button -> move immediately to tab_button.
1306 button_host->MouseEnteredButton(app_button);
1307 button_host->MouseExitedButton(app_button);
1308 button_host->MouseEnteredButton(platform_button);
1309 EXPECT_FALSE(tooltip_manager->IsVisible());
1310 EXPECT_EQ(platform_button, GetTooltipAnchorView());
1313 // Verify a fix for crash caused by a tooltip update for a deletedshelf
1314 // button, see crbug.com/288838.
1315 TEST_F(ShelfViewTest, RemovingItemClosesTooltip) {
1316 ShelfButtonHost* button_host = shelf_view_;
1317 ShelfTooltipManager* tooltip_manager = shelf_view_->tooltip_manager();
1319 // Add an item to the shelf.
1320 ShelfID app_button_id = AddAppShortcut();
1321 ShelfButton* app_button = GetButtonByID(app_button_id);
1323 // Spawn a tooltip on that item.
1324 button_host->MouseEnteredButton(app_button);
1325 ShowTooltip();
1326 EXPECT_TRUE(tooltip_manager->IsVisible());
1328 // Remove the app shortcut while the tooltip is open. The tooltip should be
1329 // closed.
1330 RemoveByID(app_button_id);
1331 EXPECT_FALSE(tooltip_manager->IsVisible());
1333 // Change the shelf layout. This should not crash.
1334 Shell::GetInstance()->SetShelfAlignment(SHELF_ALIGNMENT_LEFT,
1335 Shell::GetPrimaryRootWindow());
1338 // Changing the shelf alignment closes any open tooltip.
1339 TEST_F(ShelfViewTest, ShelfAlignmentClosesTooltip) {
1340 ShelfButtonHost* button_host = shelf_view_;
1341 ShelfTooltipManager* tooltip_manager = shelf_view_->tooltip_manager();
1343 // Add an item to the shelf.
1344 ShelfID app_button_id = AddAppShortcut();
1345 ShelfButton* app_button = GetButtonByID(app_button_id);
1347 // Spawn a tooltip on the item.
1348 button_host->MouseEnteredButton(app_button);
1349 ShowTooltip();
1350 EXPECT_TRUE(tooltip_manager->IsVisible());
1352 // Changing shelf alignment hides the tooltip.
1353 Shell::GetInstance()->SetShelfAlignment(SHELF_ALIGNMENT_LEFT,
1354 Shell::GetPrimaryRootWindow());
1355 EXPECT_FALSE(tooltip_manager->IsVisible());
1358 TEST_F(ShelfViewTest, ShouldHideTooltipTest) {
1359 ShelfID app_button_id = AddAppShortcut();
1360 ShelfID platform_button_id = AddPlatformApp();
1362 // The tooltip shouldn't hide if the mouse is on normal buttons.
1363 for (int i = 0; i < test_api_->GetButtonCount(); i++) {
1364 ShelfButton* button = test_api_->GetButton(i);
1365 if (!button)
1366 continue;
1368 EXPECT_FALSE(shelf_view_->ShouldHideTooltip(
1369 button->GetMirroredBounds().CenterPoint()))
1370 << "ShelfView tries to hide on button " << i;
1373 // The tooltip should not hide on the app-list button.
1374 views::View* app_list_button = shelf_view_->GetAppListButtonView();
1375 EXPECT_FALSE(shelf_view_->ShouldHideTooltip(
1376 app_list_button->GetMirroredBounds().CenterPoint()));
1378 // The tooltip shouldn't hide if the mouse is in the gap between two buttons.
1379 gfx::Rect app_button_rect = GetButtonByID(app_button_id)->GetMirroredBounds();
1380 gfx::Rect platform_button_rect =
1381 GetButtonByID(platform_button_id)->GetMirroredBounds();
1382 ASSERT_FALSE(app_button_rect.Intersects(platform_button_rect));
1383 EXPECT_FALSE(shelf_view_->ShouldHideTooltip(
1384 gfx::UnionRects(app_button_rect, platform_button_rect).CenterPoint()));
1386 // The tooltip should hide if it's outside of all buttons.
1387 gfx::Rect all_area;
1388 for (int i = 0; i < test_api_->GetButtonCount(); i++) {
1389 ShelfButton* button = test_api_->GetButton(i);
1390 if (!button)
1391 continue;
1393 all_area.Union(button->GetMirroredBounds());
1395 all_area.Union(shelf_view_->GetAppListButtonView()->GetMirroredBounds());
1396 EXPECT_FALSE(shelf_view_->ShouldHideTooltip(all_area.origin()));
1397 EXPECT_FALSE(shelf_view_->ShouldHideTooltip(
1398 gfx::Point(all_area.right() - 1, all_area.bottom() - 1)));
1399 EXPECT_TRUE(shelf_view_->ShouldHideTooltip(
1400 gfx::Point(all_area.right(), all_area.y())));
1401 EXPECT_TRUE(shelf_view_->ShouldHideTooltip(
1402 gfx::Point(all_area.x() - 1, all_area.y())));
1403 EXPECT_TRUE(shelf_view_->ShouldHideTooltip(
1404 gfx::Point(all_area.x(), all_area.y() - 1)));
1405 EXPECT_TRUE(shelf_view_->ShouldHideTooltip(
1406 gfx::Point(all_area.x(), all_area.bottom())));
1409 TEST_F(ShelfViewTest, ShouldHideTooltipWithAppListWindowTest) {
1410 Shell::GetInstance()->ShowAppList(NULL);
1411 ASSERT_TRUE(Shell::GetInstance()->GetAppListWindow());
1413 // The tooltip shouldn't hide if the mouse is on normal buttons.
1414 for (int i = 1; i < test_api_->GetButtonCount(); i++) {
1415 ShelfButton* button = test_api_->GetButton(i);
1416 if (!button)
1417 continue;
1419 EXPECT_FALSE(shelf_view_->ShouldHideTooltip(
1420 button->GetMirroredBounds().CenterPoint()))
1421 << "ShelfView tries to hide on button " << i;
1424 // The tooltip should hide on the app-list button.
1425 views::View* app_list_button = shelf_view_->GetAppListButtonView();
1426 EXPECT_TRUE(shelf_view_->ShouldHideTooltip(
1427 app_list_button->GetMirroredBounds().CenterPoint()));
1430 // Test that by moving the mouse cursor off the button onto the bubble it closes
1431 // the bubble.
1432 TEST_F(ShelfViewTest, ShouldHideTooltipWhenHoveringOnTooltip) {
1433 ShelfTooltipManager* tooltip_manager = shelf_view_->tooltip_manager();
1434 tooltip_manager->CreateZeroDelayTimerForTest();
1435 ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow());
1437 // Move the mouse off any item and check that no tooltip is shown.
1438 generator.MoveMouseTo(gfx::Point(0, 0));
1439 EXPECT_FALSE(tooltip_manager->IsVisible());
1441 // Move the mouse over the button and check that it is visible.
1442 views::View* app_list_button = shelf_view_->GetAppListButtonView();
1443 gfx::Rect bounds = app_list_button->GetBoundsInScreen();
1444 generator.MoveMouseTo(bounds.CenterPoint());
1445 // Wait for the timer to go off.
1446 RunAllPendingInMessageLoop();
1447 EXPECT_TRUE(tooltip_manager->IsVisible());
1449 // Move the mouse cursor slightly to the right of the item. The tooltip should
1450 // stay open.
1451 generator.MoveMouseBy(bounds.width() / 2 + 5, 0);
1452 // Make sure there is no delayed close.
1453 RunAllPendingInMessageLoop();
1454 EXPECT_TRUE(tooltip_manager->IsVisible());
1456 // Move back - it should still stay open.
1457 generator.MoveMouseBy(-(bounds.width() / 2 + 5), 0);
1458 // Make sure there is no delayed close.
1459 RunAllPendingInMessageLoop();
1460 EXPECT_TRUE(tooltip_manager->IsVisible());
1462 // Now move the mouse cursor slightly above the item - so that it is over the
1463 // tooltip bubble. Now it should disappear.
1464 generator.MoveMouseBy(0, -(bounds.height() / 2 + 5));
1465 // Wait until the delayed close kicked in.
1466 RunAllPendingInMessageLoop();
1467 EXPECT_FALSE(tooltip_manager->IsVisible());
1470 // Resizing shelf view while an add animation without fade-in is running,
1471 // which happens when overflow happens. App list button should end up in its
1472 // new ideal bounds.
1473 TEST_F(ShelfViewTest, ResizeDuringOverflowAddAnimation) {
1474 // All buttons should be visible.
1475 ASSERT_EQ(test_api_->GetButtonCount(),
1476 test_api_->GetLastVisibleIndex() + 1);
1478 // Add buttons until overflow. Let the non-overflow add animations finish but
1479 // leave the last running.
1480 int items_added = 0;
1481 AddPlatformAppNoWait();
1482 while (!test_api_->IsOverflowButtonVisible()) {
1483 test_api_->RunMessageLoopUntilAnimationsDone();
1484 AddPlatformAppNoWait();
1485 ++items_added;
1486 ASSERT_LT(items_added, 10000);
1489 // Resize shelf view with that animation running and stay overflown.
1490 gfx::Rect bounds = shelf_view_->bounds();
1491 bounds.set_width(bounds.width() - kShelfSize);
1492 shelf_view_->SetBoundsRect(bounds);
1493 ASSERT_TRUE(test_api_->IsOverflowButtonVisible());
1495 // Finish the animation.
1496 test_api_->RunMessageLoopUntilAnimationsDone();
1498 // App list button should ends up in its new ideal bounds.
1499 const int app_list_button_index = test_api_->GetButtonCount() - 1;
1500 const gfx::Rect& app_list_ideal_bounds =
1501 test_api_->GetIdealBoundsByIndex(app_list_button_index);
1502 const gfx::Rect& app_list_bounds =
1503 test_api_->GetBoundsByIndex(app_list_button_index);
1504 EXPECT_EQ(app_list_ideal_bounds, app_list_bounds);
1507 // Checks the overflow bubble size when an item is ripped off and re-inserted.
1508 TEST_F(ShelfViewTest, OverflowBubbleSize) {
1509 shelf_delegate_->set_is_app_pinned(true);
1510 AddButtonsUntilOverflow();
1511 // Add one more button to prevent the overflow bubble to disappear upon
1512 // dragging an item out on windows (flakiness, see crbug.com/436131).
1513 AddAppShortcut();
1515 // Show overflow bubble.
1516 test_api_->ShowOverflowBubble();
1517 ASSERT_TRUE(test_api_->overflow_bubble() &&
1518 test_api_->overflow_bubble()->IsShowing());
1520 ShelfViewTestAPI test_for_overflow_view(
1521 test_api_->overflow_bubble()->shelf_view());
1523 int ripped_index = test_for_overflow_view.GetLastVisibleIndex();
1524 gfx::Size bubble_size = test_for_overflow_view.GetPreferredSize();
1525 int item_width = test_for_overflow_view.GetButtonSize() +
1526 test_for_overflow_view.GetButtonSpacing();
1528 ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow(),
1529 gfx::Point());
1530 ShelfButton* button = test_for_overflow_view.GetButton(ripped_index);
1531 // Rip off the last visible item.
1532 gfx::Point start_point = button->GetBoundsInScreen().CenterPoint();
1533 gfx::Point rip_off_point(start_point.x(), 0);
1534 generator.MoveMouseTo(start_point.x(), start_point.y());
1535 base::MessageLoop::current()->RunUntilIdle();
1536 generator.PressLeftButton();
1537 base::MessageLoop::current()->RunUntilIdle();
1538 generator.MoveMouseTo(rip_off_point.x(), rip_off_point.y());
1539 base::MessageLoop::current()->RunUntilIdle();
1540 test_for_overflow_view.RunMessageLoopUntilAnimationsDone();
1542 // Check the overflow bubble size when an item is ripped off.
1543 EXPECT_EQ(bubble_size.width() - item_width,
1544 test_for_overflow_view.GetPreferredSize().width());
1545 ASSERT_TRUE(test_api_->overflow_bubble() &&
1546 test_api_->overflow_bubble()->IsShowing());
1548 // Re-insert an item into the overflow bubble.
1549 int first_index = test_for_overflow_view.GetFirstVisibleIndex();
1550 button = test_for_overflow_view.GetButton(first_index);
1552 // Check the bubble size after an item is re-inserted.
1553 generator.MoveMouseTo(button->GetBoundsInScreen().CenterPoint());
1554 test_for_overflow_view.RunMessageLoopUntilAnimationsDone();
1555 EXPECT_EQ(bubble_size.width(),
1556 test_for_overflow_view.GetPreferredSize().width());
1558 generator.ReleaseLeftButton();
1559 test_for_overflow_view.RunMessageLoopUntilAnimationsDone();
1560 EXPECT_EQ(bubble_size.width(),
1561 test_for_overflow_view.GetPreferredSize().width());
1564 // Check the drag insertion bounds of scrolled overflow bubble.
1565 TEST_F(ShelfViewTest, CheckDragInsertBoundsOfScrolledOverflowBubble) {
1566 UpdateDisplay("400x300");
1568 EXPECT_EQ(2, model_->item_count());
1570 AddButtonsUntilOverflow();
1572 // Show overflow bubble.
1573 test_api_->ShowOverflowBubble();
1574 ASSERT_TRUE(test_api_->overflow_bubble() &&
1575 test_api_->overflow_bubble()->IsShowing());
1577 int item_width = test_api_->GetButtonSize() +
1578 test_api_->GetButtonSpacing();
1579 OverflowBubbleView* bubble_view = test_api_->overflow_bubble()->bubble_view();
1580 test::OverflowBubbleViewTestAPI bubble_view_api(bubble_view);
1582 // Add more buttons until OverflowBubble is scrollable and it has 3 invisible
1583 // items.
1584 while (bubble_view_api.GetContentsSize().width() <
1585 (bubble_view->GetContentsBounds().width() + 3 * item_width))
1586 AddAppShortcut();
1588 ASSERT_TRUE(test_api_->overflow_bubble() &&
1589 test_api_->overflow_bubble()->IsShowing());
1591 ShelfViewTestAPI test_for_overflow_view(
1592 test_api_->overflow_bubble()->shelf_view());
1593 int first_index = test_for_overflow_view.GetFirstVisibleIndex();
1594 int last_index = test_for_overflow_view.GetLastVisibleIndex();
1596 ShelfButton* first_button = test_for_overflow_view.GetButton(first_index);
1597 ShelfButton* last_button = 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));
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));
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;
1621 UpdateDisplay("800x600,800x600");
1622 Shelf* secondary_shelf = Shelf::ForWindow(Shell::GetAllRootWindows()[1]);
1623 ShelfView* shelf_view_for_secondary =
1624 ShelfTestAPI(secondary_shelf).shelf_view();
1626 // The bounds should be big enough for 4 buttons + overflow chevron.
1627 shelf_view_for_secondary->SetBounds(0, 0, 500, kShelfSize);
1629 ShelfViewTestAPI test_api_for_secondary(shelf_view_for_secondary);
1630 // Speeds up animation for test.
1631 test_api_for_secondary.SetAnimationDuration(1);
1633 AddButtonsUntilOverflow();
1635 // Test #1: Test drag insertion bounds of primary shelf.
1636 // Show overflow bubble.
1637 test_api_->ShowOverflowBubble();
1638 ASSERT_TRUE(test_api_->overflow_bubble() &&
1639 test_api_->overflow_bubble()->IsShowing());
1641 ShelfViewTestAPI test_api_for_overflow_view(
1642 test_api_->overflow_bubble()->shelf_view());
1644 ShelfButton* button = test_api_for_overflow_view.GetButton(
1645 test_api_for_overflow_view.GetLastVisibleIndex());
1647 // Checks that a point in shelf is contained in drag insert bounds.
1648 gfx::Point point_in_shelf_view = button->GetBoundsInScreen().CenterPoint();
1649 gfx::Rect drag_reinsert_bounds =
1650 test_api_for_overflow_view.GetBoundsForDragInsertInScreen();
1651 EXPECT_TRUE(drag_reinsert_bounds.Contains(point_in_shelf_view));
1652 // Checks that a point out of shelf is not contained in drag insert bounds.
1653 EXPECT_FALSE(drag_reinsert_bounds.Contains(
1654 gfx::Point(point_in_shelf_view.x(), 0)));
1656 // Test #2: Test drag insertion bounds of secondary shelf.
1657 // Show overflow bubble.
1658 test_api_for_secondary.ShowOverflowBubble();
1659 ASSERT_TRUE(test_api_for_secondary.overflow_bubble() &&
1660 test_api_for_secondary.overflow_bubble()->IsShowing());
1662 ShelfViewTestAPI test_api_for_overflow_view_of_secondary(
1663 test_api_for_secondary.overflow_bubble()->shelf_view());
1665 ShelfButton* button_in_secondary =
1666 test_api_for_overflow_view_of_secondary.GetButton(
1667 test_api_for_overflow_view_of_secondary.GetLastVisibleIndex());
1669 // Checks that a point in shelf is contained in drag insert bounds.
1670 gfx::Point point_in_secondary_shelf_view =
1671 button_in_secondary->GetBoundsInScreen().CenterPoint();
1672 gfx::Rect drag_reinsert_bounds_in_secondary =
1673 test_api_for_overflow_view_of_secondary.GetBoundsForDragInsertInScreen();
1674 EXPECT_TRUE(drag_reinsert_bounds_in_secondary.Contains(
1675 point_in_secondary_shelf_view));
1676 // Checks that a point out of shelf is not contained in drag insert bounds.
1677 EXPECT_FALSE(drag_reinsert_bounds_in_secondary.Contains(
1678 gfx::Point(point_in_secondary_shelf_view.x(), 0)));
1679 // Checks that a point of overflow bubble in primary shelf should not be
1680 // contained by insert bounds of secondary shelf.
1681 EXPECT_FALSE(drag_reinsert_bounds_in_secondary.Contains(point_in_shelf_view));
1684 // Checks the rip an item off from left aligned shelf in secondary monitor.
1685 TEST_F(ShelfViewTest, CheckRipOffFromLeftShelfAlignmentWithMultiMonitor) {
1686 // win8-aura doesn't support multiple display.
1687 if (!SupportsMultipleDisplays())
1688 return;
1690 UpdateDisplay("800x600,800x600");
1691 ASSERT_EQ(2U, Shell::GetAllRootWindows().size());
1693 aura::Window* second_root = Shell::GetAllRootWindows()[1];
1695 Shell::GetInstance()->SetShelfAlignment(SHELF_ALIGNMENT_LEFT, second_root);
1696 ASSERT_EQ(SHELF_ALIGNMENT_LEFT,
1697 Shell::GetInstance()->GetShelfAlignment(second_root));
1699 // Initially, app list and browser shortcut are added.
1700 EXPECT_EQ(2, model_->item_count());
1701 int browser_index = model_->GetItemIndexForType(TYPE_BROWSER_SHORTCUT);
1702 EXPECT_GT(browser_index, 0);
1704 Shelf* secondary_shelf = Shelf::ForWindow(second_root);
1705 ShelfView* shelf_view_for_secondary =
1706 ShelfTestAPI(secondary_shelf).shelf_view();
1708 ShelfViewTestAPI test_api_for_secondary_shelf_view(shelf_view_for_secondary);
1709 ShelfButton* button =
1710 test_api_for_secondary_shelf_view.GetButton(browser_index);
1712 // Fetch the start point of dragging.
1713 gfx::Point start_point = button->GetBoundsInScreen().CenterPoint();
1714 ::wm::ConvertPointFromScreen(second_root, &start_point);
1716 ui::test::EventGenerator generator(second_root, start_point);
1718 // Rip off the browser item.
1719 generator.PressLeftButton();
1720 generator.MoveMouseTo(start_point.x() + 400, start_point.y());
1721 test_api_for_secondary_shelf_view.RunMessageLoopUntilAnimationsDone();
1722 EXPECT_TRUE(test_api_for_secondary_shelf_view.IsRippedOffFromShelf());
1725 // Checks various drag and drop operations from OverflowBubble to Shelf.
1726 TEST_F(ShelfViewTest, CheckDragAndDropFromOverflowBubbleToShelf) {
1727 AddButtonsUntilOverflow();
1728 // Add one more button to prevent the overflow bubble to disappear upon
1729 // dragging an item out on windows (flakiness, see crbug.com/425097).
1730 AddAppShortcut();
1732 TestDraggingAnItemFromOverflowToShelf(false);
1733 TestDraggingAnItemFromOverflowToShelf(true);
1736 // Tests that the AppListButton renders as active in response to touches.
1737 TEST_F(ShelfViewTest, AppListButtonTouchFeedback) {
1738 AppListButton* app_list_button =
1739 static_cast<AppListButton*>(shelf_view_->GetAppListButtonView());
1740 EXPECT_FALSE(app_list_button->draw_background_as_active());
1742 ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow());
1743 generator.set_current_location(app_list_button->
1744 GetBoundsInScreen().CenterPoint());
1745 generator.PressTouch();
1746 EXPECT_TRUE(app_list_button->draw_background_as_active());
1748 generator.ReleaseTouch();
1749 EXPECT_FALSE(app_list_button->draw_background_as_active());
1750 EXPECT_TRUE(Shell::GetInstance()->GetAppListTargetVisibility());
1753 // Tests that a touch that slides out of the bounds of the AppListButton leads
1754 // to the end of rendering an active state.
1755 TEST_F(ShelfViewTest, AppListButtonTouchFeedbackCancellation) {
1756 AppListButton* app_list_button =
1757 static_cast<AppListButton*>(shelf_view_->GetAppListButtonView());
1758 EXPECT_FALSE(app_list_button->draw_background_as_active());
1760 ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow());
1761 generator.set_current_location(app_list_button->
1762 GetBoundsInScreen().CenterPoint());
1763 generator.PressTouch();
1764 EXPECT_TRUE(app_list_button->draw_background_as_active());
1766 gfx::Point moved_point(app_list_button->GetBoundsInScreen().right() + 1,
1767 app_list_button->
1768 GetBoundsInScreen().CenterPoint().y());
1769 generator.MoveTouch(moved_point);
1770 EXPECT_FALSE(app_list_button->draw_background_as_active());
1772 generator.set_current_location(moved_point);
1773 generator.ReleaseTouch();
1774 EXPECT_FALSE(app_list_button->draw_background_as_active());
1775 EXPECT_FALSE(Shell::GetInstance()->GetAppListTargetVisibility());
1778 // Verifies that Launcher_ButtonPressed_* UMA user actions are recorded when an
1779 // item is selected.
1780 TEST_F(ShelfViewTest,
1781 Launcher_ButtonPressedUserActionsRecordedWhenItemSelected) {
1782 base::UserActionTester user_action_tester;
1784 ShelfID browser_shelf_id = model_->items()[browser_index_].id;
1785 ShelfItemSelectionTracker* selection_tracker = new ShelfItemSelectionTracker;
1786 item_manager_->SetShelfItemDelegate(
1787 browser_shelf_id,
1788 scoped_ptr<ShelfItemDelegate>(selection_tracker).Pass());
1790 SimulateClick(browser_index_);
1791 EXPECT_EQ(1,
1792 user_action_tester.GetActionCount("Launcher_ButtonPressed_Mouse"));
1795 // Verifies that Launcher_*Task UMA user actions are recorded when an item is
1796 // selected.
1797 TEST_F(ShelfViewTest, Launcher_TaskUserActionsRecordedWhenItemSelected) {
1798 base::UserActionTester user_action_tester;
1800 ShelfID browser_shelf_id = model_->items()[browser_index_].id;
1801 ShelfItemSelectionTracker* selection_tracker = new ShelfItemSelectionTracker;
1802 selection_tracker->set_item_selected_action(
1803 ShelfItemDelegate::kNewWindowCreated);
1804 item_manager_->SetShelfItemDelegate(
1805 browser_shelf_id,
1806 scoped_ptr<ShelfItemDelegate>(selection_tracker).Pass());
1808 SimulateClick(browser_index_);
1809 EXPECT_EQ(1, user_action_tester.GetActionCount("Launcher_LaunchTask"));
1812 // Verifies that a Launcher_ButtonPressed_Mouse UMA user action is recorded when
1813 // an icon is activated by a mouse event.
1814 TEST_F(ShelfViewTest,
1815 Launcher_ButtonPressed_MouseIsRecordedWhenIconActivatedByMouse) {
1816 base::UserActionTester user_action_tester;
1817 ui::MouseEvent mouse_event(ui::ET_MOUSE_PRESSED, gfx::Point(), gfx::Point(),
1818 base::TimeDelta(), 0, 0);
1819 test_api_->RecordIconActivatedSource(mouse_event);
1820 EXPECT_EQ(1,
1821 user_action_tester.GetActionCount("Launcher_ButtonPressed_Mouse"));
1824 // Verifies that a Launcher_ButtonPressed_Touch UMA user action is recorded when
1825 // an icon is activated by a touch event.
1826 TEST_F(ShelfViewTest,
1827 Launcher_ButtonPressed_MouseIsRecordedWhenIconActivatedByTouch) {
1828 base::UserActionTester user_action_tester;
1829 ui::TouchEvent touch_event(ui::ET_GESTURE_TAP, gfx::Point(), 0,
1830 base::TimeDelta());
1831 test_api_->RecordIconActivatedSource(touch_event);
1832 EXPECT_EQ(1,
1833 user_action_tester.GetActionCount("Launcher_ButtonPressed_Touch"));
1836 // Verifies that a Launcher_LaunchTask UMA user action is recorded when
1837 // selecting an icon causes a new window to be created.
1838 TEST_F(ShelfViewTest, Launcher_LaunchTaskIsRecordedWhenNewWindowIsCreated) {
1839 base::UserActionTester user_action_tester;
1840 test_api_->RecordIconActivatedAction(ShelfItemDelegate::kNewWindowCreated);
1841 EXPECT_EQ(1, user_action_tester.GetActionCount("Launcher_LaunchTask"));
1844 // Verifies that a Launcher_MinimizeTask UMA user action is recorded when
1845 // selecting an icon causes an existing window to be minimized.
1846 TEST_F(ShelfViewTest, Launcher_MinimizeTaskIsRecordedWhenWindowIsMinimized) {
1847 base::UserActionTester user_action_tester;
1848 test_api_->RecordIconActivatedAction(
1849 ShelfItemDelegate::kExistingWindowMinimized);
1850 EXPECT_EQ(1, user_action_tester.GetActionCount("Launcher_MinimizeTask"));
1853 // Verifies that a Launcher_SwitchTask UMA user action is recorded when
1854 // selecting an icon causes an existing window to be activated.
1855 TEST_F(ShelfViewTest,
1856 Launcher_SwitchTaskIsRecordedWhenExistingWindowIsActivated) {
1857 base::UserActionTester user_action_tester;
1858 test_api_->RecordIconActivatedAction(
1859 ShelfItemDelegate::kExistingWindowActivated);
1860 EXPECT_EQ(1, user_action_tester.GetActionCount("Launcher_SwitchTask"));
1863 class ShelfViewVisibleBoundsTest : public ShelfViewTest,
1864 public testing::WithParamInterface<bool> {
1865 public:
1866 ShelfViewVisibleBoundsTest() : text_direction_change_(GetParam()) {}
1868 void CheckAllItemsAreInBounds() {
1869 gfx::Rect visible_bounds = shelf_view_->GetVisibleItemsBoundsInScreen();
1870 gfx::Rect shelf_bounds = shelf_view_->GetBoundsInScreen();
1871 EXPECT_TRUE(shelf_bounds.Contains(visible_bounds));
1872 for (int i = 0; i < test_api_->GetButtonCount(); ++i)
1873 if (ShelfButton* button = test_api_->GetButton(i))
1874 EXPECT_TRUE(visible_bounds.Contains(button->GetBoundsInScreen()));
1875 CheckAppListButtonIsInBounds();
1878 void CheckAppListButtonIsInBounds() {
1879 gfx::Rect visible_bounds = shelf_view_->GetVisibleItemsBoundsInScreen();
1880 gfx::Rect app_list_button_bounds = shelf_view_->GetAppListButtonView()->
1881 GetBoundsInScreen();
1882 EXPECT_TRUE(visible_bounds.Contains(app_list_button_bounds));
1885 private:
1886 ScopedTextDirectionChange text_direction_change_;
1888 DISALLOW_COPY_AND_ASSIGN(ShelfViewVisibleBoundsTest);
1891 TEST_P(ShelfViewVisibleBoundsTest, ItemsAreInBounds) {
1892 // Adding elements leaving some empty space.
1893 for (int i = 0; i < 3; i++) {
1894 AddAppShortcut();
1896 test_api_->RunMessageLoopUntilAnimationsDone();
1897 EXPECT_FALSE(test_api_->IsOverflowButtonVisible());
1898 CheckAllItemsAreInBounds();
1899 // Same for overflow case.
1900 while (!test_api_->IsOverflowButtonVisible()) {
1901 AddAppShortcut();
1903 test_api_->RunMessageLoopUntilAnimationsDone();
1904 CheckAllItemsAreInBounds();
1907 INSTANTIATE_TEST_CASE_P(LtrRtl, ShelfViewTextDirectionTest, testing::Bool());
1908 INSTANTIATE_TEST_CASE_P(VisibleBounds, ShelfViewVisibleBoundsTest,
1909 testing::Bool());
1911 } // namespace test
1912 } // namespace ash