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"
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"
57 ////////////////////////////////////////////////////////////////////////////////
58 // ShelfIconObserver tests.
60 class TestShelfIconObserver
: public ShelfIconObserver
{
62 explicit TestShelfIconObserver(Shelf
* shelf
)
64 change_notified_(false) {
66 shelf_
->AddIconObserver(this);
69 ~TestShelfIconObserver() override
{
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; }
82 bool change_notified_
;
84 DISALLOW_COPY_AND_ASSIGN(TestShelfIconObserver
);
87 class ShelfViewIconObserverTest
: public AshTestBase
{
89 ShelfViewIconObserverTest() {}
90 ~ShelfViewIconObserverTest() override
{}
92 void SetUp() override
{
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
{
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]);
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
{
127 ShelfItemSelectionTracker()
128 : TestShelfItemDelegate(NULL
),
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.
147 // TestShelfItemDelegate:
148 ShelfItemDelegate::PerformedAction
ItemSelected(
149 const ui::Event
& event
) override
{
151 return item_selected_action_
;
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());
180 widget
->GetNativeWindow()->parent()->RemoveChild(widget
->GetNativeWindow());
181 shelf_view_test()->RunMessageLoopUntilAnimationsDone();
182 EXPECT_TRUE(observer()->change_notified());
186 // Sometimes fails on trybots on win7_aura. http://crbug.com/177135
188 #define MAYBE_AddRemoveWithMultipleDisplays \
189 DISABLED_AddRemoveWithMultipleDisplays
191 #define MAYBE_AddRemoveWithMultipleDisplays \
192 AddRemoveWithMultipleDisplays
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());
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());
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());
238 ////////////////////////////////////////////////////////////////////////////////
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
{
246 explicit TestShelfDelegateForShelfView(ShelfModel
* 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
{
259 EXPECT_TRUE(base::StringToInt(app_id
, &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
);
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(); }
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().
292 DISALLOW_COPY_AND_ASSIGN(TestShelfDelegateForShelfView
);
295 class ShelfViewTest
: public AshTestBase
{
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;
329 AshTestBase::TearDown();
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();
349 ShelfID
AddAppShortcut() {
351 item
.type
= TYPE_APP_SHORTCUT
;
352 item
.status
= STATUS_CLOSED
;
354 ShelfID id
= model_
->next_id();
356 CreateAndSetShelfItemDelegateForID(id
);
357 test_api_
->RunMessageLoopUntilAnimationsDone();
362 ShelfID id
= AddPanelNoWait();
363 test_api_
->RunMessageLoopUntilAnimationsDone();
367 ShelfID
AddPlatformAppNoWait() {
369 item
.type
= TYPE_PLATFORM_APP
;
370 item
.status
= STATUS_RUNNING
;
372 ShelfID id
= model_
->next_id();
374 CreateAndSetShelfItemDelegateForID(id
);
378 ShelfID
AddPanelNoWait() {
380 item
.type
= TYPE_APP_PANEL
;
381 item
.status
= STATUS_RUNNING
;
383 ShelfID id
= model_
->next_id();
385 CreateAndSetShelfItemDelegateForID(id
);
389 ShelfID
AddPlatformApp() {
390 ShelfID id
= AddPlatformAppNoWait();
391 test_api_
->RunMessageLoopUntilAnimationsDone();
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
);
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();
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
));
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
,
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
);
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
,
476 int destination_index
) {
477 ShelfButtonHost
* button_host
= shelf_view_
;
478 views::View
* button
= SimulateButtonPressed(pointer
, button_index
);
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
);
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() {
516 while (!test_api_
->IsOverflowButtonVisible()) {
519 ASSERT_LT(items_added
, 10000);
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|.
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|
570 gfx::Point
modified_drop_point(drop_point
.x() - item_width
/ 4,
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());
579 drag_button
->OnMouseCaptureLost();
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.
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));
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
) {
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_
);
631 ShelfView
* shelf_view_
;
633 ShelfItemDelegateManager
* item_manager_
;
635 // Owned by ash::Shell.
636 TestShelfDelegateForShelfView
* shelf_delegate_
;
638 scoped_ptr
<ShelfViewTestAPI
> test_api_
;
641 DISALLOW_COPY_AND_ASSIGN(ShelfViewTest
);
644 class ScopedTextDirectionChange
{
646 explicit ScopedTextDirectionChange(bool is_rtl
) : is_rtl_(is_rtl
) {
647 original_locale_
= l10n_util::GetApplicationLocale(std::string());
649 base::i18n::SetICUDefaultLocale("he");
650 CheckTextDirectionIsCorrect();
653 ~ScopedTextDirectionChange() {
655 base::i18n::SetICUDefaultLocale(original_locale_
);
659 void CheckTextDirectionIsCorrect() {
660 ASSERT_EQ(is_rtl_
, base::i18n::IsRTL());
664 std::string original_locale_
;
667 class ShelfViewTextDirectionTest
668 : public ShelfViewTest
,
669 public testing::WithParamInterface
<bool> {
671 ShelfViewTextDirectionTest() : text_direction_change_(GetParam()) {}
672 virtual ~ShelfViewTextDirectionTest() {}
674 void SetUp() override
{ ShelfViewTest::SetUp(); }
676 void TearDown() override
{ ShelfViewTest::TearDown(); }
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
702 TEST_F(ShelfViewTest
, OverflowButtonBounds
) {
703 ShelfID first_id
= AddPlatformApp();
704 ShelfID overflow_id
= AddPlatformApp();
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();
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
,
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
,
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.
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();
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
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.
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();
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
819 ShelfID first_added
= AddPlatformApp();
820 EXPECT_TRUE(GetButtonByID(first_added
)->visible());
822 ShelfID added
= AddPlatformApp();
823 if (test_api_
->IsOverflowButtonVisible()) {
824 EXPECT_FALSE(GetButtonByID(added
)->visible());
829 ASSERT_LT(items_added
, 10000);
832 ShelfID panel
= AddPanel();
833 EXPECT_TRUE(test_api_
->IsOverflowButtonVisible());
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
;
856 while (!test_api_
->IsOverflowButtonVisible()) {
857 last_panel
= AddPanel();
859 ASSERT_LT(items_added
, 10000);
862 // The first panel should now be hidden by the new platform apps needing
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.
871 while (GetButtonByID(platform_app
)->visible() &&
872 GetButtonByID(last_panel
)->visible()) {
873 platform_app
= AddPlatformApp();
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
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
895 for (int i
= 0; i
< 2; ++i
) {
896 ShelfID id
= button_ids
.back();
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
913 const ShelfAlignment kAlignments
[] = {
914 SHELF_ALIGNMENT_LEFT
,
915 SHELF_ALIGNMENT_RIGHT
,
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
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())) {
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
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.
947 ShelfID first_added
= AddPlatformApp();
948 ShelfID last_added
= first_added
;
949 while (!test_api_
->IsOverflowButtonVisible()) {
950 last_added
= AddPlatformApp();
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.
977 ShelfID last_added
= AddPlatformApp();
978 while (!test_api_
->IsOverflowButtonVisible()) {
979 last_added
= AddPlatformApp();
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.
997 while (!test_api_
->IsOverflowButtonVisible()) {
998 AddPlatformAppNoWait();
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
);
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
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,
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,
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,
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
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,
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,
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
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.
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,
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(
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
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(
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());
1288 EXPECT_TRUE(tooltip_manager
->IsVisible());
1290 // Once it's visible, it keeps visibility and is pointing to the same
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
);
1326 EXPECT_TRUE(tooltip_manager
->IsVisible());
1328 // Remove the app shortcut while the tooltip is open. The tooltip should be
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
);
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
);
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.
1388 for (int i
= 0; i
< test_api_
->GetButtonCount(); i
++) {
1389 ShelfButton
* button
= test_api_
->GetButton(i
);
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
);
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
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
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();
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).
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(),
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
1584 while (bubble_view_api
.GetContentsSize().width() <
1585 (bubble_view
->GetContentsBounds().width() + 3 * item_width
))
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())
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())
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).
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,
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(
1788 scoped_ptr
<ShelfItemDelegate
>(selection_tracker
).Pass());
1790 SimulateClick(browser_index_
);
1792 user_action_tester
.GetActionCount("Launcher_ButtonPressed_Mouse"));
1795 // Verifies that Launcher_*Task UMA user actions are recorded when an item is
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(
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
);
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,
1831 test_api_
->RecordIconActivatedSource(touch_event
);
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> {
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
));
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
++) {
1896 test_api_
->RunMessageLoopUntilAnimationsDone();
1897 EXPECT_FALSE(test_api_
->IsOverflowButtonVisible());
1898 CheckAllItemsAreInBounds();
1899 // Same for overflow case.
1900 while (!test_api_
->IsOverflowButtonVisible()) {
1903 test_api_
->RunMessageLoopUntilAnimationsDone();
1904 CheckAllItemsAreInBounds();
1907 INSTANTIATE_TEST_CASE_P(LtrRtl
, ShelfViewTextDirectionTest
, testing::Bool());
1908 INSTANTIATE_TEST_CASE_P(VisibleBounds
, ShelfViewVisibleBoundsTest
,