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.
7 #include "ash/root_window_controller.h"
8 #include "ash/shelf/shelf_layout_manager.h"
10 #include "ash/shell_delegate.h"
11 #include "ash/system/tray/system_tray.h"
12 #include "ash/system/tray/tray_constants.h"
13 #include "ash/system/user/tray_user.h"
14 #include "ash/system/user/tray_user_separator.h"
15 #include "ash/test/ash_test_base.h"
16 #include "ash/test/test_session_state_delegate.h"
17 #include "ash/test/test_shell_delegate.h"
18 #include "components/user_manager/user_info.h"
19 #include "ui/events/test/event_generator.h"
20 #include "ui/gfx/animation/animation_container_element.h"
21 #include "ui/views/view.h"
22 #include "ui/views/widget/widget.h"
26 class TrayUserTest
: public ash::test::AshTestBase
{
31 void SetUp() override
;
33 // This has to be called prior to first use with the proper configuration.
34 void InitializeParameters(int users_logged_in
, bool multiprofile
);
36 // Show the system tray menu using the provided event generator.
37 void ShowTrayMenu(ui::test::EventGenerator
* generator
);
39 // Move the mouse over the user item.
40 void MoveOverUserItem(ui::test::EventGenerator
* generator
, int index
);
42 // Click on the user item. Note that the tray menu needs to be shown.
43 void ClickUserItem(ui::test::EventGenerator
* generator
, int index
);
45 // Accessors to various system components.
46 ShelfLayoutManager
* shelf() { return shelf_
; }
47 SystemTray
* tray() { return tray_
; }
48 ash::test::TestSessionStateDelegate
* delegate() { return delegate_
; }
49 ash::TrayUser
* tray_user(int index
) { return tray_user_
[index
]; }
50 ash::TrayUserSeparator
* tray_user_separator() { return tray_user_separator_
; }
53 ShelfLayoutManager
* shelf_
;
55 ash::test::TestSessionStateDelegate
* delegate_
;
57 // Note that the ownership of these items is on the shelf.
58 std::vector
<ash::TrayUser
*> tray_user_
;
60 // The separator between the tray users and the rest of the menu.
61 // Note: The item will get owned by the shelf.
62 TrayUserSeparator
* tray_user_separator_
;
64 DISALLOW_COPY_AND_ASSIGN(TrayUserTest
);
67 TrayUserTest::TrayUserTest()
71 tray_user_separator_(NULL
) {
74 void TrayUserTest::SetUp() {
75 ash::test::AshTestBase::SetUp();
76 shelf_
= Shell::GetPrimaryRootWindowController()->GetShelfLayoutManager();
77 tray_
= Shell::GetPrimaryRootWindowController()->GetSystemTray();
78 delegate_
= static_cast<ash::test::TestSessionStateDelegate
*>(
79 ash::Shell::GetInstance()->session_state_delegate());
82 void TrayUserTest::InitializeParameters(int users_logged_in
,
85 shelf()->LayoutShelf();
86 shelf()->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_NEVER
);
88 // Set our default assumptions. Note that it is sufficient to set these
89 // after everything was created.
90 delegate_
->set_logged_in_users(users_logged_in
);
91 ash::test::TestShellDelegate
* shell_delegate
=
92 static_cast<ash::test::TestShellDelegate
*>(
93 ash::Shell::GetInstance()->delegate());
94 shell_delegate
->set_multi_profiles_enabled(multiprofile
);
96 // Instead of using the existing tray panels we create new ones which makes
98 for (int i
= 0; i
< delegate_
->GetMaximumNumberOfLoggedInUsers(); i
++) {
99 tray_user_
.push_back(new ash::TrayUser(tray_
, i
));
100 tray_
->AddTrayItem(tray_user_
[i
]);
102 // We then add also the separator.
103 tray_user_separator_
= new ash::TrayUserSeparator(tray_
);
104 tray_
->AddTrayItem(tray_user_separator_
);
107 void TrayUserTest::ShowTrayMenu(ui::test::EventGenerator
* generator
) {
108 gfx::Point center
= tray()->GetBoundsInScreen().CenterPoint();
110 generator
->MoveMouseTo(center
.x(), center
.y());
111 EXPECT_FALSE(tray()->IsAnyBubbleVisible());
112 generator
->ClickLeftButton();
115 void TrayUserTest::MoveOverUserItem(ui::test::EventGenerator
* generator
,
118 tray_user(index
)->GetUserPanelBoundsInScreenForTest().CenterPoint();
120 generator
->MoveMouseTo(center
.x(), center
.y());
123 void TrayUserTest::ClickUserItem(ui::test::EventGenerator
* generator
,
125 MoveOverUserItem(generator
, index
);
126 generator
->ClickLeftButton();
129 // Make sure that we show items for all users in the tray accordingly.
130 TEST_F(TrayUserTest
, CheckTrayItemSize
) {
131 InitializeParameters(1, false);
132 tray_user(0)->UpdateAfterLoginStatusChangeForTest(user::LOGGED_IN_GUEST
);
133 gfx::Size size
= tray_user(0)->GetLayoutSizeForTest();
134 EXPECT_EQ(kTrayItemSize
, size
.height());
135 tray_user(0)->UpdateAfterLoginStatusChangeForTest(user::LOGGED_IN_USER
);
136 size
= tray_user(0)->GetLayoutSizeForTest();
137 EXPECT_EQ(kTrayItemSize
, size
.height());
140 // Make sure that in single user mode the user panel cannot be activated and no
141 // separators are being created.
142 TEST_F(TrayUserTest
, SingleUserModeDoesNotAllowAddingUser
) {
143 InitializeParameters(1, false);
145 // Move the mouse over the status area and click to open the status menu.
146 ui::test::EventGenerator
generator(Shell::GetPrimaryRootWindow());
148 EXPECT_FALSE(tray()->IsAnyBubbleVisible());
150 for (int i
= 0; i
< delegate()->GetMaximumNumberOfLoggedInUsers(); i
++)
151 EXPECT_EQ(ash::TrayUser::HIDDEN
, tray_user(i
)->GetStateForTest());
152 EXPECT_FALSE(tray_user_separator()->separator_shown());
154 ShowTrayMenu(&generator
);
156 EXPECT_TRUE(tray()->HasSystemBubble());
157 EXPECT_TRUE(tray()->IsAnyBubbleVisible());
159 for (int i
= 0; i
< delegate()->GetMaximumNumberOfLoggedInUsers(); i
++)
160 EXPECT_EQ(i
== 0 ? ash::TrayUser::SHOWN
: ash::TrayUser::HIDDEN
,
161 tray_user(i
)->GetStateForTest());
162 EXPECT_FALSE(tray_user_separator()->separator_shown());
163 tray()->CloseSystemBubble();
166 #if defined(OS_CHROMEOS)
167 // Make sure that in multi user mode the user panel can be activated and there
168 // will be one panel for each user plus one additional separator at the end.
169 // Note: the mouse watcher (for automatic closing upon leave) cannot be tested
170 // here since it does not work with the event system in unit tests.
171 TEST_F(TrayUserTest
, MutiUserModeDoesNotAllowToAddUser
) {
172 InitializeParameters(1, true);
174 // Move the mouse over the status area and click to open the status menu.
175 ui::test::EventGenerator
generator(Shell::GetPrimaryRootWindow());
176 generator
.set_async(false);
178 int max_users
= delegate()->GetMaximumNumberOfLoggedInUsers();
179 // Checking now for each amount of users that the correct is done.
180 for (int j
= 1; j
< max_users
; j
++) {
181 // Set the number of logged in users.
182 delegate()->set_logged_in_users(j
);
184 // Verify that nothing is shown.
185 EXPECT_FALSE(tray()->IsAnyBubbleVisible());
186 for (int i
= 0; i
< max_users
; i
++)
187 EXPECT_FALSE(tray_user(i
)->GetStateForTest());
188 EXPECT_FALSE(tray_user_separator()->separator_shown());
189 // After clicking on the tray the menu should get shown and for each logged
190 // in user we should get a visible item. In addition, the separator should
191 // show up when we reach more then one user.
192 ShowTrayMenu(&generator
);
194 EXPECT_TRUE(tray()->HasSystemBubble());
195 EXPECT_TRUE(tray()->IsAnyBubbleVisible());
196 for (int i
= 0; i
< max_users
; i
++) {
197 EXPECT_EQ(i
< j
? ash::TrayUser::SHOWN
: ash::TrayUser::HIDDEN
,
198 tray_user(i
)->GetStateForTest());
201 // Check the visibility of the separator.
202 EXPECT_EQ(j
> 1 ? true : false, tray_user_separator()->separator_shown());
204 // Move the mouse over the user item and it should hover.
205 MoveOverUserItem(&generator
, 0);
206 EXPECT_EQ(ash::TrayUser::HOVERED
, tray_user(0)->GetStateForTest());
207 for (int i
= 1; i
< max_users
; i
++) {
208 EXPECT_EQ(i
< j
? ash::TrayUser::SHOWN
: ash::TrayUser::HIDDEN
,
209 tray_user(i
)->GetStateForTest());
212 // Check that clicking the button allows to add item if we have still room
213 // for one more user.
214 ClickUserItem(&generator
, 0);
215 EXPECT_EQ(j
== max_users
? ash::TrayUser::ACTIVE_BUT_DISABLED
216 : ash::TrayUser::ACTIVE
,
217 tray_user(0)->GetStateForTest());
219 // Click the button again to see that the menu goes away.
220 ClickUserItem(&generator
, 0);
221 EXPECT_EQ(ash::TrayUser::HOVERED
, tray_user(0)->GetStateForTest());
223 // Close and check that everything is deleted.
224 tray()->CloseSystemBubble();
225 EXPECT_FALSE(tray()->IsAnyBubbleVisible());
226 for (int i
= 0; i
< delegate()->GetMaximumNumberOfLoggedInUsers(); i
++)
227 EXPECT_EQ(ash::TrayUser::HIDDEN
, tray_user(i
)->GetStateForTest());
231 // Make sure that user changing gets properly executed.
232 TEST_F(TrayUserTest
, MutiUserModeButtonClicks
) {
234 InitializeParameters(2, true);
235 ui::test::EventGenerator
generator(Shell::GetPrimaryRootWindow());
236 ShowTrayMenu(&generator
);
238 // Switch to a new user - which has a capitalized name.
239 ClickUserItem(&generator
, 1);
240 const user_manager::UserInfo
* active_user
= delegate()->GetActiveUserInfo();
241 const user_manager::UserInfo
* second_user
= delegate()->GetUserInfo(1);
242 EXPECT_EQ(active_user
->GetUserID(), second_user
->GetUserID());
243 // Since the name is capitalized, the email should be different then the
245 EXPECT_NE(active_user
->GetUserID(), second_user
->GetEmail());
246 tray()->CloseSystemBubble();