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. 4 5#include <vector> 6 7#include "ash/root_window_controller.h" 8#include "ash/shelf/shelf_layout_manager.h" 9#include "ash/shell.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" 23 24namespace ash { 25 26class TrayUserTest : public ash::test::AshTestBase { 27 public: 28 TrayUserTest(); 29 30 // testing::Test: 31 virtual void SetUp() OVERRIDE; 32 33 // This has to be called prior to first use with the proper configuration. 34 void InitializeParameters(int users_logged_in, bool multiprofile); 35 36 // Show the system tray menu using the provided event generator. 37 void ShowTrayMenu(ui::test::EventGenerator* generator); 38 39 // Move the mouse over the user item. 40 void MoveOverUserItem(ui::test::EventGenerator* generator, int index); 41 42 // Click on the user item. Note that the tray menu needs to be shown. 43 void ClickUserItem(ui::test::EventGenerator* generator, int index); 44 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_; } 51 52 private: 53 ShelfLayoutManager* shelf_; 54 SystemTray* tray_; 55 ash::test::TestSessionStateDelegate* delegate_; 56 57 // Note that the ownership of these items is on the shelf. 58 std::vector<ash::TrayUser*> tray_user_; 59 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_; 63 64 DISALLOW_COPY_AND_ASSIGN(TrayUserTest); 65}; 66 67TrayUserTest::TrayUserTest() 68 : shelf_(NULL), 69 tray_(NULL), 70 delegate_(NULL), 71 tray_user_separator_(NULL) { 72} 73 74void 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()); 80} 81 82void TrayUserTest::InitializeParameters(int users_logged_in, 83 bool multiprofile) { 84 // Show the shelf. 85 shelf()->LayoutShelf(); 86 shelf()->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_NEVER); 87 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); 95 96 // Instead of using the existing tray panels we create new ones which makes 97 // the access easier. 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]); 101 } 102 // We then add also the separator. 103 tray_user_separator_ = new ash::TrayUserSeparator(tray_); 104 tray_->AddTrayItem(tray_user_separator_); 105} 106 107void TrayUserTest::ShowTrayMenu(ui::test::EventGenerator* generator) { 108 gfx::Point center = tray()->GetBoundsInScreen().CenterPoint(); 109 110 generator->MoveMouseTo(center.x(), center.y()); 111 EXPECT_FALSE(tray()->IsAnyBubbleVisible()); 112 generator->ClickLeftButton(); 113} 114 115void TrayUserTest::MoveOverUserItem(ui::test::EventGenerator* generator, 116 int index) { 117 gfx::Point center = 118 tray_user(index)->GetUserPanelBoundsInScreenForTest().CenterPoint(); 119 120 generator->MoveMouseTo(center.x(), center.y()); 121} 122 123void TrayUserTest::ClickUserItem(ui::test::EventGenerator* generator, 124 int index) { 125 MoveOverUserItem(generator, index); 126 generator->ClickLeftButton(); 127} 128 129// Make sure that we show items for all users in the tray accordingly. 130TEST_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()); 138} 139 140// Make sure that in single user mode the user panel cannot be activated and no 141// separators are being created. 142TEST_F(TrayUserTest, SingleUserModeDoesNotAllowAddingUser) { 143 InitializeParameters(1, false); 144 145 // Move the mouse over the status area and click to open the status menu. 146 ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow()); 147 148 EXPECT_FALSE(tray()->IsAnyBubbleVisible()); 149 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()); 153 154 ShowTrayMenu(&generator); 155 156 EXPECT_TRUE(tray()->HasSystemBubble()); 157 EXPECT_TRUE(tray()->IsAnyBubbleVisible()); 158 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(); 164} 165 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. 171TEST_F(TrayUserTest, MutiUserModeDoesNotAllowToAddUser) { 172 InitializeParameters(1, true); 173 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); 177 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); 183 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); 193 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()); 199 } 200 201 // Check the visibility of the separator. 202 EXPECT_EQ(j > 1 ? true : false, tray_user_separator()->separator_shown()); 203 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()); 210 } 211 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()); 218 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()); 222 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()); 228 } 229} 230 231// Make sure that user changing gets properly executed. 232TEST_F(TrayUserTest, MutiUserModeButtonClicks) { 233 // Have two users. 234 InitializeParameters(2, true); 235 ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow()); 236 ShowTrayMenu(&generator); 237 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 244 // user_id. 245 EXPECT_NE(active_user->GetUserID(), second_user->GetEmail()); 246 tray()->CloseSystemBubble(); 247} 248 249#endif 250 251} // namespace ash 252