1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "ash/system/tray/tray_details_view.h"
7 #include "ash/root_window_controller.h"
8 #include "ash/shelf/shelf_widget.h"
10 #include "ash/system/status_area_widget.h"
11 #include "ash/system/tray/hover_highlight_view.h"
12 #include "ash/system/tray/special_popup_row.h"
13 #include "ash/system/tray/system_tray.h"
14 #include "ash/system/tray/system_tray_item.h"
15 #include "ash/system/tray/tray_popup_header_button.h"
16 #include "ash/system/tray/view_click_listener.h"
17 #include "ash/test/ash_test_base.h"
18 #include "base/run_loop.h"
19 #include "grit/ash_resources.h"
20 #include "grit/ash_strings.h"
21 #include "ui/aura/window.h"
22 #include "ui/events/test/event_generator.h"
23 #include "ui/views/controls/button/button.h"
24 #include "ui/views/view.h"
25 #include "ui/views/widget/widget.h"
32 SystemTray
* GetSystemTray() {
33 return Shell::GetPrimaryRootWindowController()->shelf()->
34 status_area_widget()->system_tray();
37 class TestDetailsView
: public TrayDetailsView
,
38 public ViewClickListener
,
39 public views::ButtonListener
{
41 explicit TestDetailsView(SystemTrayItem
* owner
) : TrayDetailsView(owner
) {
42 // Uses bluetooth label for testing purpose. It can be changed to any
44 CreateSpecialRow(IDS_ASH_STATUS_TRAY_BLUETOOTH
, this);
45 tray_popup_header_button_
=
46 new TrayPopupHeaderButton(this, IDR_AURA_UBER_TRAY_BLUETOOTH_ENABLED
,
47 IDR_AURA_UBER_TRAY_BLUETOOTH_DISABLED
,
48 IDR_AURA_UBER_TRAY_BLUETOOTH_ENABLED_HOVER
,
49 IDR_AURA_UBER_TRAY_BLUETOOTH_DISABLED_HOVER
,
50 IDS_ASH_STATUS_TRAY_BLUETOOTH
);
51 footer()->AddButton(tray_popup_header_button_
);
54 ~TestDetailsView() override
{}
56 TrayPopupHeaderButton
* tray_popup_header_button() {
57 return tray_popup_header_button_
;
61 footer()->content()->RequestFocus();
65 void OnViewClicked(views::View
* sender
) override
{}
67 // views::ButtonListener:
68 void ButtonPressed(views::Button
* sender
, const ui::Event
& event
) override
{}
71 TrayPopupHeaderButton
* tray_popup_header_button_
;
73 DISALLOW_COPY_AND_ASSIGN(TestDetailsView
);
76 // Trivial item implementation that tracks its views for testing.
77 class TestItem
: public SystemTrayItem
{
79 TestItem() : SystemTrayItem(GetSystemTray()), tray_view_(NULL
) {}
81 // Overridden from SystemTrayItem:
82 views::View
* CreateTrayView(user::LoginStatus status
) override
{
83 tray_view_
= new views::View
;
86 views::View
* CreateDefaultView(user::LoginStatus status
) override
{
87 default_view_
= new views::View
;
88 default_view_
->SetFocusable(true);
91 views::View
* CreateDetailedView(user::LoginStatus status
) override
{
92 detailed_view_
= new TestDetailsView(this);
93 return detailed_view_
;
95 void DestroyTrayView() override
{ tray_view_
= NULL
; }
96 void DestroyDefaultView() override
{ default_view_
= NULL
; }
97 void DestroyDetailedView() override
{ detailed_view_
= NULL
; }
99 views::View
* tray_view() const { return tray_view_
; }
100 views::View
* default_view() const { return default_view_
; }
101 TestDetailsView
* detailed_view() const { return detailed_view_
; }
104 views::View
* tray_view_
;
105 views::View
* default_view_
;
106 TestDetailsView
* detailed_view_
;
108 DISALLOW_COPY_AND_ASSIGN(TestItem
);
113 class TrayDetailsViewTest
: public AshTestBase
{
115 TrayDetailsViewTest() {}
116 ~TrayDetailsViewTest() override
{}
118 HoverHighlightView
* CreateAndShowHoverHighlightView() {
119 SystemTray
* tray
= GetSystemTray();
120 TestItem
* test_item
= new TestItem
;
121 tray
->AddTrayItem(test_item
);
122 tray
->ShowDefaultView(BUBBLE_CREATE_NEW
);
123 RunAllPendingInMessageLoop();
124 tray
->ShowDetailedView(test_item
, 0, true, BUBBLE_USE_EXISTING
);
125 RunAllPendingInMessageLoop();
127 return static_cast<HoverHighlightView
*>(test_item
->detailed_view()->
128 footer()->content());
131 TrayPopupHeaderButton
* CreateAndShowTrayPopupHeaderButton() {
132 SystemTray
* tray
= GetSystemTray();
133 TestItem
* test_item
= new TestItem
;
134 tray
->AddTrayItem(test_item
);
135 tray
->ShowDefaultView(BUBBLE_CREATE_NEW
);
136 RunAllPendingInMessageLoop();
137 tray
->ShowDetailedView(test_item
, 0, true, BUBBLE_USE_EXISTING
);
138 RunAllPendingInMessageLoop();
140 return test_item
->detailed_view()->tray_popup_header_button();
144 DISALLOW_COPY_AND_ASSIGN(TrayDetailsViewTest
);
147 TEST_F(TrayDetailsViewTest
, TransitionToDefaultViewTest
) {
148 SystemTray
* tray
= GetSystemTray();
149 ASSERT_TRUE(tray
->GetWidget());
151 TestItem
* test_item_1
= new TestItem
;
152 TestItem
* test_item_2
= new TestItem
;
153 tray
->AddTrayItem(test_item_1
);
154 tray
->AddTrayItem(test_item_2
);
156 // Ensure the tray views are created.
157 ASSERT_TRUE(test_item_1
->tray_view() != NULL
);
158 ASSERT_TRUE(test_item_2
->tray_view() != NULL
);
160 // Show the default view.
161 tray
->ShowDefaultView(BUBBLE_CREATE_NEW
);
162 RunAllPendingInMessageLoop();
164 // Show the detailed view of item 2.
165 tray
->ShowDetailedView(test_item_2
, 0, true, BUBBLE_USE_EXISTING
);
166 EXPECT_TRUE(test_item_2
->detailed_view());
167 RunAllPendingInMessageLoop();
168 EXPECT_FALSE(test_item_2
->default_view());
170 // Transition back to default view, the default view of item 2 should have
172 test_item_2
->detailed_view()->FocusFooter();
173 test_item_2
->detailed_view()->TransitionToDefaultView();
174 RunAllPendingInMessageLoop();
176 EXPECT_TRUE(test_item_2
->default_view());
177 EXPECT_FALSE(test_item_2
->detailed_view());
178 EXPECT_TRUE(test_item_2
->default_view()->HasFocus());
180 // Show the detailed view of item 2 again.
181 tray
->ShowDetailedView(test_item_2
, 0, true, BUBBLE_USE_EXISTING
);
182 EXPECT_TRUE(test_item_2
->detailed_view());
183 RunAllPendingInMessageLoop();
184 EXPECT_FALSE(test_item_2
->default_view());
186 // Transition back to default view, the default view of item 2 should NOT have
188 test_item_2
->detailed_view()->TransitionToDefaultView();
189 RunAllPendingInMessageLoop();
191 EXPECT_TRUE(test_item_2
->default_view());
192 EXPECT_FALSE(test_item_2
->detailed_view());
193 EXPECT_FALSE(test_item_2
->default_view()->HasFocus());
196 // Tests that HoverHighlightView enters hover state in response to touch.
197 TEST_F(TrayDetailsViewTest
, HoverHighlightViewTouchFeedback
) {
198 HoverHighlightView
* view
= CreateAndShowHoverHighlightView();
199 EXPECT_FALSE(view
->hover());
201 ui::test::EventGenerator
generator(Shell::GetPrimaryRootWindow());
202 generator
.set_current_location(view
->GetBoundsInScreen().CenterPoint());
203 generator
.PressTouch();
204 EXPECT_TRUE(view
->hover());
206 generator
.ReleaseTouch();
207 EXPECT_FALSE(view
->hover());
210 // Tests that touch events leaving HoverHighlightView cancel the hover state.
211 TEST_F(TrayDetailsViewTest
, HoverHighlightViewTouchFeedbackCancellation
) {
212 HoverHighlightView
* view
= CreateAndShowHoverHighlightView();
213 EXPECT_FALSE(view
->hover());
215 gfx::Rect view_bounds
= view
->GetBoundsInScreen();
216 ui::test::EventGenerator
generator(Shell::GetPrimaryRootWindow());
217 generator
.set_current_location(view_bounds
.CenterPoint());
218 generator
.PressTouch();
219 EXPECT_TRUE(view
->hover());
221 gfx::Point
move_point(view_bounds
.x(), view_bounds
.CenterPoint().y());
222 generator
.MoveTouch(move_point
);
223 EXPECT_FALSE(view
->hover());
225 generator
.set_current_location(move_point
);
226 generator
.ReleaseTouch();
227 EXPECT_FALSE(view
->hover());
230 // Tests that TrayPopupHeaderButton renders a background in response to touch.
231 TEST_F(TrayDetailsViewTest
, TrayPopupHeaderButtonTouchFeedback
) {
232 TrayPopupHeaderButton
* button
= CreateAndShowTrayPopupHeaderButton();
233 EXPECT_FALSE(button
->background());
235 ui::test::EventGenerator
generator(Shell::GetPrimaryRootWindow());
236 generator
.set_current_location(button
->GetBoundsInScreen().CenterPoint());
237 generator
.PressTouch();
238 EXPECT_TRUE(button
->background());
240 generator
.ReleaseTouch();
241 EXPECT_FALSE(button
->background());
244 // Tests that touch events leaving TrayPopupHeaderButton cancel the touch
245 // feedback background.
246 TEST_F(TrayDetailsViewTest
, TrayPopupHeaderButtonTouchFeedbackCancellation
) {
247 TrayPopupHeaderButton
* button
= CreateAndShowTrayPopupHeaderButton();
248 EXPECT_FALSE(button
->background());
250 gfx::Rect view_bounds
= button
->GetBoundsInScreen();
251 ui::test::EventGenerator
generator(Shell::GetPrimaryRootWindow());
252 generator
.set_current_location(view_bounds
.CenterPoint());
253 generator
.PressTouch();
254 EXPECT_TRUE(button
->background());
256 gfx::Point
move_point(view_bounds
.x(), view_bounds
.CenterPoint().y());
257 generator
.MoveTouch(move_point
);
258 EXPECT_FALSE(button
->background());
260 generator
.set_current_location(move_point
);
261 generator
.ReleaseTouch();
262 EXPECT_FALSE(button
->background());
265 // Tests that a mouse entering TrayPopupHeaderButton renders a background as
267 TEST_F(TrayDetailsViewTest
, TrayPopupHeaderButtonMouseHoverFeedback
) {
268 TrayPopupHeaderButton
* button
= CreateAndShowTrayPopupHeaderButton();
269 EXPECT_FALSE(button
->background());
271 ui::test::EventGenerator
generator(Shell::GetPrimaryRootWindow());
272 gfx::Rect bounds
= button
->GetBoundsInScreen();
273 gfx::Point
initial_point(bounds
.x() - 1, bounds
.y());
274 generator
.set_current_location(initial_point
);
275 generator
.MoveMouseBy(1, 0);
276 RunAllPendingInMessageLoop();
277 EXPECT_TRUE(button
->background());