summaryrefslogtreecommitdiffstats
path: root/chromium/ash/system/user/tray_user_unittest.cc
blob: ad6966104f89e1368af74802771b25b88c82791a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <vector>

#include "ash/ash_switches.h"
#include "ash/root_window_controller.h"
#include "ash/shelf/shelf_layout_manager.h"
#include "ash/shell.h"
#include "ash/shell_delegate.h"
#include "ash/system/tray/system_tray.h"
#include "ash/system/user/tray_user.h"
#include "ash/system/user/tray_user_separator.h"
#include "ash/test/ash_test_base.h"
#include "ash/test/test_session_state_delegate.h"
#include "ash/test/test_shell_delegate.h"
#include "base/command_line.h"
#include "ui/aura/test/event_generator.h"
#include "ui/gfx/animation/animation_container_element.h"
#include "ui/views/view.h"
#include "ui/views/widget/widget.h"

#if defined(OS_CHROMEOS)
#include "ash/system/tray/system_tray_notifier.h"
#endif

namespace ash {
namespace internal {

class TrayUserTest : public ash::test::AshTestBase {
 public:
  TrayUserTest();

  // testing::Test:
  virtual void SetUp() OVERRIDE;

  // This has to be called prior to first use with the proper configuration.
  void InitializeParameters(int users_logged_in, bool multiprofile);

  // Show the system tray menu using the provided event generator.
  void ShowTrayMenu(aura::test::EventGenerator* generator);

  // Move the mouse over the user item.
  void MoveOverUserItem(aura::test::EventGenerator* generator, int index);

  // Click on the user item. Note that the tray menu needs to be shown.
  void ClickUserItem(aura::test::EventGenerator* generator, int index);

  // Accessors to various system components.
  ShelfLayoutManager* shelf() { return shelf_; }
  SystemTray* tray() { return tray_; }
  ash::test::TestSessionStateDelegate* delegate() { return delegate_; }
  ash::internal::TrayUser* tray_user(int index) { return tray_user_[index]; }
  ash::internal::TrayUserSeparator* tray_user_separator() {
    return tray_user_separator_;
  }

 private:
  ShelfLayoutManager* shelf_;
  SystemTray* tray_;
  ash::test::TestSessionStateDelegate* delegate_;

  // Note that the ownership of these items is on the shelf.
  std::vector<ash::internal::TrayUser*> tray_user_;

  // The separator between the tray users and the rest of the menu.
  // Note: The item will get owned by the shelf.
  TrayUserSeparator* tray_user_separator_;

  DISALLOW_COPY_AND_ASSIGN(TrayUserTest);
};

#if defined(OS_CHROMEOS)
// The tray user test which tests functionality where multiple tray items are
// visible in the system tray.
class MultiTrayUserTest : public TrayUserTest {
 public:
  MultiTrayUserTest() {}

  virtual void SetUp() OVERRIDE {
    CommandLine* command_line = CommandLine::ForCurrentProcess();
    command_line->AppendSwitch(ash::switches::kAshEnableMultiUserTray);
    TrayUserTest::SetUp();
  }

 private:
  DISALLOW_COPY_AND_ASSIGN(MultiTrayUserTest);
};
#endif

TrayUserTest::TrayUserTest()
    : shelf_(NULL),
      tray_(NULL),
      delegate_(NULL),
      tray_user_separator_(NULL) {
}

void TrayUserTest::SetUp() {
  ash::test::AshTestBase::SetUp();
  shelf_ = Shell::GetPrimaryRootWindowController()->GetShelfLayoutManager();
  tray_ = Shell::GetPrimaryRootWindowController()->GetSystemTray();
  delegate_ = static_cast<ash::test::TestSessionStateDelegate*>(
      ash::Shell::GetInstance()->session_state_delegate());
}

void TrayUserTest::InitializeParameters(int users_logged_in,
                                        bool multiprofile) {
  // Show the shelf.
  shelf()->LayoutShelf();
  shelf()->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_NEVER);

  // Set our default assumptions. Note that it is sufficient to set these
  // after everything was created.
  delegate_->set_logged_in_users(users_logged_in);
  ash::test::TestShellDelegate* shell_delegate =
      static_cast<ash::test::TestShellDelegate*>(
          ash::Shell::GetInstance()->delegate());
  shell_delegate->set_multi_profiles_enabled(multiprofile);

  // Instead of using the existing tray panels we create new ones which makes
  // the access easier.
  for (int i = 0; i < delegate_->GetMaximumNumberOfLoggedInUsers(); i++) {
    tray_user_.push_back(new ash::internal::TrayUser(tray_, i));
    tray_->AddTrayItem(tray_user_[i]);
  }
  // We then add also the separator.
  tray_user_separator_ = new ash::internal::TrayUserSeparator(tray_);
  tray_->AddTrayItem(tray_user_separator_);
}

void TrayUserTest::ShowTrayMenu(aura::test::EventGenerator* generator) {
  gfx::Point center = tray()->GetBoundsInScreen().CenterPoint();

  generator->MoveMouseTo(center.x(), center.y());
  EXPECT_FALSE(tray()->IsAnyBubbleVisible());
  generator->ClickLeftButton();
}

void TrayUserTest::MoveOverUserItem(aura::test::EventGenerator* generator,
    int index) {
  gfx::Point center =
      tray_user(index)->GetUserPanelBoundsInScreenForTest().CenterPoint();

  generator->MoveMouseTo(center.x(), center.y());
}

void TrayUserTest::ClickUserItem(aura::test::EventGenerator* generator,
                                 int index) {
  MoveOverUserItem(generator, index);
  generator->ClickLeftButton();
}

// Make sure that in single user mode the user panel cannot be activated and no
// separators are being created.
TEST_F(TrayUserTest, SingleUserModeDoesNotAllowAddingUser) {
  InitializeParameters(1, false);

  // Move the mouse over the status area and click to open the status menu.
  aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow());

  EXPECT_FALSE(tray()->IsAnyBubbleVisible());

  for (int i = 0; i < delegate()->GetMaximumNumberOfLoggedInUsers(); i++)
    EXPECT_EQ(ash::internal::TrayUser::HIDDEN,
              tray_user(i)->GetStateForTest());
  EXPECT_FALSE(tray_user_separator()->separator_shown());

  ShowTrayMenu(&generator);

  EXPECT_TRUE(tray()->HasSystemBubble());
  EXPECT_TRUE(tray()->IsAnyBubbleVisible());

  for (int i = 0; i < delegate()->GetMaximumNumberOfLoggedInUsers(); i++)
    EXPECT_EQ(i == 0 ? ash::internal::TrayUser::SHOWN :
                       ash::internal::TrayUser::HIDDEN,
              tray_user(i)->GetStateForTest());
  EXPECT_FALSE(tray_user_separator()->separator_shown());
  tray()->CloseSystemBubble();
}

#if defined(OS_CHROMEOS)
// Make sure that in multi user mode the user panel can be activated and there
// will be one panel for each user plus one additional separator at the end.
// Note: the mouse watcher (for automatic closing upon leave) cannot be tested
// here since it does not work with the event system in unit tests.
TEST_F(TrayUserTest, MutiUserModeDoesNotAllowToAddUser) {
  InitializeParameters(1, true);

  // Move the mouse over the status area and click to open the status menu.
  aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow());
  generator.set_async(false);

  int max_users = delegate()->GetMaximumNumberOfLoggedInUsers();
  // Checking now for each amount of users that the correct is done.
  for (int j = 1; j < max_users; j++) {
    // Set the number of logged in users.
    delegate()->set_logged_in_users(j);

    // Verify that nothing is shown.
    EXPECT_FALSE(tray()->IsAnyBubbleVisible());
    for (int i = 0; i < max_users; i++)
      EXPECT_FALSE(tray_user(i)->GetStateForTest());
    EXPECT_FALSE(tray_user_separator()->separator_shown());
    // After clicking on the tray the menu should get shown and for each logged
    // in user we should get a visible item. In addition, the separator should
    // show up when we reach more then one user.
    ShowTrayMenu(&generator);

    EXPECT_TRUE(tray()->HasSystemBubble());
    EXPECT_TRUE(tray()->IsAnyBubbleVisible());
    for (int i = 0; i < max_users; i++) {
      EXPECT_EQ(i < j ? ash::internal::TrayUser::SHOWN :
                        ash::internal::TrayUser::HIDDEN,
                tray_user(i)->GetStateForTest());
    }

    // Check the visibility of the separator.
    EXPECT_EQ(j > 1 ? true : false, tray_user_separator()->separator_shown());

    // Move the mouse over the user item and it should hover.
    MoveOverUserItem(&generator, 0);
    EXPECT_EQ(ash::internal::TrayUser::HOVERED,
              tray_user(0)->GetStateForTest());
    for (int i = 1; i < max_users; i++) {
      EXPECT_EQ(i < j ? ash::internal::TrayUser::SHOWN :
                        ash::internal::TrayUser::HIDDEN,
                tray_user(i)->GetStateForTest());
    }

    // Check that clicking the button allows to add item if we have still room
    // for one more user.
    ClickUserItem(&generator, 0);
    EXPECT_EQ(j == max_users ?
                  ash::internal::TrayUser::ACTIVE_BUT_DISABLED :
                  ash::internal::TrayUser::ACTIVE,
              tray_user(0)->GetStateForTest());

    // Click the button again to see that the menu goes away.
    ClickUserItem(&generator, 0);
    EXPECT_EQ(ash::internal::TrayUser::HOVERED,
              tray_user(0)->GetStateForTest());

    // Close and check that everything is deleted.
    tray()->CloseSystemBubble();
    EXPECT_FALSE(tray()->IsAnyBubbleVisible());
    for (int i = 0; i < delegate()->GetMaximumNumberOfLoggedInUsers(); i++)
      EXPECT_EQ(ash::internal::TrayUser::HIDDEN,
                tray_user(i)->GetStateForTest());
  }
}

// Make sure that user changing gets properly executed.
TEST_F(TrayUserTest, MutiUserModeButtonClicks) {
  // Have two users.
  InitializeParameters(2, true);
  aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow());
  ShowTrayMenu(&generator);

  // Switch to a new user - which has a capitalized name.
  ClickUserItem(&generator, 1);
  EXPECT_EQ(delegate()->get_activated_user(), delegate()->GetUserID(1));
  // Since the name is capitalized, the email should be different then the
  // user_id.
  EXPECT_NE(delegate()->get_activated_user(), delegate()->GetUserEmail(1));
  tray()->CloseSystemBubble();
}

// Make sure that we show items for all users in the tray accordingly.
TEST_F(MultiTrayUserTest, CheckTrayUserItems) {
  InitializeParameters(1, true);

  int max_users = delegate()->GetMaximumNumberOfLoggedInUsers();
  // Checking now for each amount of users that the proper items are visible in
  // the tray. The proper item is hereby:
  // 2 -> User #1
  // 1 -> User #2
  // 0 -> User #3
  // Note: Tray items are required to populate system tray items as well as the
  // system tray menu. The system tray menu changes it's appearance with the
  // addition of more users, but the system tray does not create new items after
  // it got created.
  for (int present_users = 1; present_users <= max_users; ++present_users) {
    // We simulate the user addition by telling the delegate the new number of
    // users, then change all user tray items and finally tell the tray to
    // re-layout itself.
    delegate()->set_logged_in_users(present_users);
    Shell::GetInstance()->system_tray_notifier()->NotifyUserAddedToSession();
    tray()->Layout();

    // Check that the tray items are being shown in the reverse order.
    for (int i = 0; i < max_users; i++) {
      gfx::Rect rect =
          tray()->GetTrayItemViewForTest(tray_user(i))->GetBoundsInScreen();
      if (max_users - 1 - i < present_users)
        EXPECT_FALSE(rect.IsEmpty());
      else
        EXPECT_TRUE(rect.IsEmpty());
    }
  }

  // Click on the last item to see that the user changes.
  aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow());
  generator.set_async(false);

  // Switch to a new user - again, note that we have to click on the reverse
  // item in the list. Since the first clickable item is 1, we get user #2.
  gfx::Point point =
      tray()->GetTrayItemViewForTest(tray_user(1))->
                         GetBoundsInScreen().CenterPoint();

  generator.MoveMouseTo(point.x(), point.y());
  generator.ClickLeftButton();
  EXPECT_EQ(delegate()->get_activated_user(), delegate()->GetUserID(1));
}

#endif

}  // namespace internal
}  // namespace ash