1 // Copyright (c) 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 "ui/message_center/views/message_popup_collection.h"
6
7 #include "base/stl_util.h"
8 #include "base/strings/string_number_conversions.h"
9 #include "base/strings/utf_string_conversions.h"
10 #include "build/build_config.h"
11 #include "ui/display/display.h"
12 #include "ui/events/base_event_utils.h"
13 #include "ui/gfx/animation/linear_animation.h"
14 #include "ui/message_center/message_center.h"
15 #include "ui/message_center/public/cpp/message_center_constants.h"
16 #include "ui/message_center/views/desktop_message_popup_collection.h"
17 #include "ui/message_center/views/message_popup_view.h"
18 #include "ui/views/test/views_test_base.h"
19
20 using message_center::MessageCenter;
21 using message_center::Notification;
22
23 namespace message_center {
24
25 namespace {
26
27 class MockMessagePopupView;
28
29 class MockMessagePopupCollection : public DesktopMessagePopupCollection {
30 public:
MockMessagePopupCollection(gfx::NativeWindow context)31 explicit MockMessagePopupCollection(gfx::NativeWindow context)
32 : DesktopMessagePopupCollection(), context_(context) {}
33
34 ~MockMessagePopupCollection() override = default;
35
SetAnimationValue(double current)36 void SetAnimationValue(double current) {
37 animation()->SetCurrentValue(current);
38 if (current == 1.0)
39 animation()->End();
40 else
41 AnimationProgressed(animation());
42 }
43
RemovePopup(MockMessagePopupView * popup)44 void RemovePopup(MockMessagePopupView* popup) {
45 base::Erase(popups_, popup);
46 }
47
IsAnimating()48 bool IsAnimating() { return animation()->is_animating(); }
49
set_is_primary_display(bool is_primary_display)50 void set_is_primary_display(bool is_primary_display) {
51 is_primary_display_ = is_primary_display;
52 }
53
set_is_fullscreen(bool is_fullscreen)54 void set_is_fullscreen(bool is_fullscreen) { is_fullscreen_ = is_fullscreen; }
55
set_new_popup_height(int new_popup_height)56 void set_new_popup_height(int new_popup_height) {
57 new_popup_height_ = new_popup_height;
58 }
59
popups()60 std::vector<MockMessagePopupView*>& popups() { return popups_; }
61
popup_timer_started() const62 bool popup_timer_started() const { return popup_timer_started_; }
63
64 protected:
65 MessagePopupView* CreatePopup(const Notification& notification) override;
66
ConfigureWidgetInitParamsForContainer(views::Widget * widget,views::Widget::InitParams * init_params)67 void ConfigureWidgetInitParamsForContainer(
68 views::Widget* widget,
69 views::Widget::InitParams* init_params) override {
70 // Provides an aura window context for widget creation.
71 init_params->context = context_;
72 }
73
RestartPopupTimers()74 void RestartPopupTimers() override {
75 MessagePopupCollection::RestartPopupTimers();
76 popup_timer_started_ = true;
77 }
78
PausePopupTimers()79 void PausePopupTimers() override {
80 MessagePopupCollection::PausePopupTimers();
81 popup_timer_started_ = false;
82 }
83
IsPrimaryDisplayForNotification() const84 bool IsPrimaryDisplayForNotification() const override {
85 return is_primary_display_;
86 }
87
BlockForMixedFullscreen(const Notification & notification) const88 bool BlockForMixedFullscreen(
89 const Notification& notification) const override {
90 return is_fullscreen_;
91 }
92
93 private:
94 gfx::NativeWindow context_;
95
96 std::vector<MockMessagePopupView*> popups_;
97
98 bool popup_timer_started_ = false;
99 bool is_primary_display_ = true;
100 bool is_fullscreen_ = false;
101 int new_popup_height_ = 84;
102
103 DISALLOW_COPY_AND_ASSIGN(MockMessagePopupCollection);
104 };
105
106 class MockMessagePopupView : public MessagePopupView {
107 public:
MockMessagePopupView(const std::string & id,int init_height,MockMessagePopupCollection * popup_collection)108 MockMessagePopupView(const std::string& id,
109 int init_height,
110 MockMessagePopupCollection* popup_collection)
111 : MessagePopupView(popup_collection),
112 popup_collection_(popup_collection),
113 id_(id),
114 title_(base::UTF16ToUTF8(
115 MessageCenter::Get()->FindVisibleNotificationById(id)->title())) {
116 auto* view = new views::View;
117 view->SetPreferredSize(gfx::Size(kNotificationWidth, init_height));
118 AddChildView(view);
119 }
120
121 ~MockMessagePopupView() override = default;
122
Close()123 void Close() override {
124 popup_collection_->RemovePopup(this);
125 MessagePopupView::Close();
126 }
127
UpdateContents(const Notification & notification)128 void UpdateContents(const Notification& notification) override {
129 if (height_after_update_.has_value())
130 SetPreferredHeight(height_after_update_.value());
131 popup_collection_->NotifyPopupResized();
132 updated_ = true;
133 title_ = base::UTF16ToUTF8(notification.title());
134 }
135
AutoCollapse()136 void AutoCollapse() override {
137 if (expandable_)
138 children().front()->SetPreferredSize(gfx::Size(kNotificationWidth, 42));
139 }
140
SetPreferredHeight(int height)141 void SetPreferredHeight(int height) {
142 children().front()->SetPreferredSize(gfx::Size(kNotificationWidth, height));
143 }
144
SetHovered(bool is_hovered)145 void SetHovered(bool is_hovered) {
146 if (is_hovered) {
147 ui::MouseEvent enter_event(ui::ET_MOUSE_ENTERED, gfx::Point(),
148 gfx::Point(), ui::EventTimeForNow(), 0, 0);
149 OnMouseEntered(enter_event);
150 } else {
151 ui::MouseEvent exit_event(ui::ET_MOUSE_EXITED, gfx::Point(), gfx::Point(),
152 ui::EventTimeForNow(), 0, 0);
153 OnMouseExited(exit_event);
154 }
155 }
156
Activate()157 void Activate() {
158 SetCanActivate(true);
159 GetWidget()->Activate();
160 }
161
id() const162 const std::string& id() const { return id_; }
updated() const163 bool updated() const { return updated_; }
164
title() const165 const std::string& title() const { return title_; }
166
set_expandable(bool expandable)167 void set_expandable(bool expandable) { expandable_ = expandable; }
168
set_height_after_update(base::Optional<int> height_after_update)169 void set_height_after_update(base::Optional<int> height_after_update) {
170 height_after_update_ = height_after_update;
171 }
172
173 private:
174 MockMessagePopupCollection* const popup_collection_;
175
176 std::string id_;
177 bool updated_ = false;
178 bool expandable_ = false;
179 std::string title_;
180
181 base::Optional<int> height_after_update_;
182 };
183
CreatePopup(const Notification & notification)184 MessagePopupView* MockMessagePopupCollection::CreatePopup(
185 const Notification& notification) {
186 auto* popup =
187 new MockMessagePopupView(notification.id(), new_popup_height_, this);
188 popups_.push_back(popup);
189 return popup;
190 }
191
192 } // namespace
193
194 class MessagePopupCollectionTest : public views::ViewsTestBase,
195 public MessageCenterObserver {
196 public:
197 MessagePopupCollectionTest() = default;
198 ~MessagePopupCollectionTest() override = default;
199
200 // views::ViewTestBase:
SetUp()201 void SetUp() override {
202 views::ViewsTestBase::SetUp();
203 MessageCenter::Initialize();
204 MessageCenter::Get()->DisableTimersForTest();
205 MessageCenter::Get()->AddObserver(this);
206
207 popup_collection_ =
208 std::make_unique<MockMessagePopupCollection>(GetContext());
209
210 // This size fits test machines resolution and also can keep a few popups
211 // w/o ill effects of hitting the screen overflow. This allows us to assume
212 // and verify normal layout of the toast stack.
213 SetDisplayInfo(gfx::Rect(0, 0, 1920, 1070), // taskbar at the bottom.
214 gfx::Rect(0, 0, 1920, 1080));
215 }
216
TearDown()217 void TearDown() override {
218 MessageCenter::Get()->RemoveAllNotifications(
219 false /* by_user */, MessageCenter::RemoveType::ALL);
220 AnimateUntilIdle();
221 popup_collection_.reset();
222
223 MessageCenter::Get()->RemoveObserver(this);
224 MessageCenter::Shutdown();
225 views::ViewsTestBase::TearDown();
226 }
227
228 // MessageCenterObserver:
OnNotificationDisplayed(const std::string & notification_id,const DisplaySource source)229 void OnNotificationDisplayed(const std::string& notification_id,
230 const DisplaySource source) override {
231 last_displayed_id_ = notification_id;
232 }
233
234 protected:
CreateNotification(const std::string & id)235 std::unique_ptr<Notification> CreateNotification(const std::string& id) {
236 return CreateNotification(id, "test title");
237 }
238
CreateNotification(const std::string & id,const std::string & title)239 std::unique_ptr<Notification> CreateNotification(const std::string& id,
240 const std::string& title) {
241 return std::make_unique<Notification>(
242 NOTIFICATION_TYPE_BASE_FORMAT, id, base::UTF8ToUTF16(title),
243 base::UTF8ToUTF16("test message"), gfx::Image(),
244 base::string16() /* display_source */, GURL(), NotifierId(),
245 RichNotificationData(), new NotificationDelegate());
246 }
247
AddNotification()248 std::string AddNotification() {
249 std::string id = base::NumberToString(id_++);
250 MessageCenter::Get()->AddNotification(CreateNotification(id));
251 return id;
252 }
253
Update()254 void Update() { popup_collection_->Update(); }
255
SetAnimationValue(double current)256 void SetAnimationValue(double current) {
257 popup_collection_->SetAnimationValue(current);
258 }
259
IsAnimating() const260 bool IsAnimating() const { return popup_collection_->IsAnimating(); }
261
AnimateUntilIdle()262 void AnimateUntilIdle() {
263 while (popup_collection_->IsAnimating()) {
264 popup_collection_->SetAnimationValue(1.0);
265 }
266 }
267
AnimateToMiddle()268 void AnimateToMiddle() {
269 EXPECT_TRUE(popup_collection_->IsAnimating());
270 popup_collection_->SetAnimationValue(0.5);
271 }
272
AnimateToEnd()273 void AnimateToEnd() {
274 EXPECT_TRUE(popup_collection_->IsAnimating());
275 popup_collection_->SetAnimationValue(1.0);
276 }
277
GetPopup(const std::string & id)278 MockMessagePopupView* GetPopup(const std::string& id) {
279 for (auto* popup : popup_collection_->popups()) {
280 if (popup->id() == id)
281 return popup;
282 }
283 return nullptr;
284 }
285
GetPopupAt(size_t index)286 MockMessagePopupView* GetPopupAt(size_t index) {
287 return popup_collection_->popups()[index];
288 }
289
GetPopupCounts() const290 size_t GetPopupCounts() const { return popup_collection_->popups().size(); }
291
SetDisplayInfo(const gfx::Rect & work_area,const gfx::Rect & display_bounds)292 void SetDisplayInfo(const gfx::Rect& work_area,
293 const gfx::Rect& display_bounds) {
294 display::Display dummy_display;
295 dummy_display.set_bounds(display_bounds);
296 dummy_display.set_work_area(work_area);
297 work_area_ = work_area;
298 popup_collection_->RecomputeAlignment(dummy_display);
299 }
300
IsPopupTimerStarted() const301 bool IsPopupTimerStarted() const {
302 return popup_collection_->popup_timer_started();
303 }
304
popup_collection() const305 MockMessagePopupCollection* popup_collection() const {
306 return popup_collection_.get();
307 }
work_area() const308 const gfx::Rect& work_area() const { return work_area_; }
309
last_displayed_id() const310 const std::string& last_displayed_id() const { return last_displayed_id_; }
311
312 private:
313 int id_ = 0;
314
315 std::unique_ptr<MockMessagePopupCollection> popup_collection_;
316
317 gfx::Rect work_area_;
318 std::string last_displayed_id_;
319
320 DISALLOW_COPY_AND_ASSIGN(MessagePopupCollectionTest);
321 };
322
TEST_F(MessagePopupCollectionTest,Nothing)323 TEST_F(MessagePopupCollectionTest, Nothing) {
324 EXPECT_FALSE(IsAnimating());
325 Update();
326 // If no popups are available, nothing changes.
327 EXPECT_FALSE(IsAnimating());
328 }
329
TEST_F(MessagePopupCollectionTest,FadeInFadeOutNotification)330 TEST_F(MessagePopupCollectionTest, FadeInFadeOutNotification) {
331 // Add a notification.
332 std::string id = AddNotification();
333 EXPECT_TRUE(IsAnimating());
334 EXPECT_EQ(1u, GetPopupCounts());
335
336 // The popup will fade in from right.
337 const int before_x = GetPopup(id)->GetBoundsInScreen().x();
338 EXPECT_EQ(0.0f, GetPopup(id)->GetOpacity());
339
340 AnimateToMiddle();
341 EXPECT_GT(before_x, GetPopup(id)->GetBoundsInScreen().x());
342 EXPECT_LT(0.0f, GetPopup(id)->GetOpacity());
343
344 AnimateToEnd();
345 EXPECT_EQ(1.0f, GetPopup(id)->GetOpacity());
346 EXPECT_FALSE(IsAnimating());
347 EXPECT_TRUE(work_area().Contains(GetPopup(id)->GetBoundsInScreen()));
348 EXPECT_EQ(id, last_displayed_id());
349
350 // The popup will fade out because of timeout.
351 MessageCenter::Get()->MarkSinglePopupAsShown(id, false);
352 EXPECT_TRUE(IsAnimating());
353
354 AnimateToMiddle();
355 EXPECT_GT(1.0f, GetPopup(id)->GetOpacity());
356
357 AnimateToEnd();
358 EXPECT_FALSE(IsAnimating());
359 EXPECT_FALSE(GetPopup(id));
360 }
361
TEST_F(MessagePopupCollectionTest,FadeInMultipleNotifications)362 TEST_F(MessagePopupCollectionTest, FadeInMultipleNotifications) {
363 std::vector<std::string> ids;
364 for (size_t i = 0; i < kMaxVisiblePopupNotifications; ++i)
365 ids.push_back(AddNotification());
366
367 for (size_t i = 0; i < ids.size(); ++i) {
368 EXPECT_EQ(ids[i], last_displayed_id());
369 EXPECT_EQ(i + 1, GetPopupCounts());
370 AnimateToMiddle();
371 EXPECT_LT(0.0f, GetPopupAt(i)->GetOpacity());
372 AnimateToEnd();
373 EXPECT_EQ(1.0f, GetPopupAt(i)->GetOpacity());
374 EXPECT_TRUE(work_area().Contains(GetPopupAt(i)->GetBoundsInScreen()));
375 }
376 EXPECT_FALSE(IsAnimating());
377
378 EXPECT_EQ(kMaxVisiblePopupNotifications, GetPopupCounts());
379
380 for (size_t i = 0; i < ids.size(); ++i)
381 EXPECT_EQ(ids[i], GetPopupAt(i)->id());
382
383 for (size_t i = 0; i < ids.size() - 1; ++i) {
384 EXPECT_GT(GetPopupAt(i)->GetBoundsInScreen().x(),
385 GetPopupAt(i + 1)->GetBoundsInScreen().bottom());
386 }
387 }
388
TEST_F(MessagePopupCollectionTest,FadeInMultipleNotificationsInverse)389 TEST_F(MessagePopupCollectionTest, FadeInMultipleNotificationsInverse) {
390 popup_collection()->set_inverse();
391
392 std::vector<std::string> ids;
393 for (size_t i = 0; i < kMaxVisiblePopupNotifications; ++i)
394 ids.push_back(AddNotification());
395
396 for (size_t i = 0; i < ids.size(); ++i) {
397 EXPECT_EQ(ids[i], last_displayed_id());
398 EXPECT_EQ(i + 1, GetPopupCounts());
399 const int before_x = GetPopupAt(i)->GetBoundsInScreen().x();
400 AnimateToMiddle();
401 EXPECT_LT(0.0f, GetPopupAt(i)->GetOpacity());
402 EXPECT_GT(before_x, GetPopupAt(i)->GetBoundsInScreen().x());
403 AnimateToEnd();
404 EXPECT_EQ(1.0f, GetPopupAt(i)->GetOpacity());
405 EXPECT_TRUE(work_area().Contains(GetPopupAt(i)->GetBoundsInScreen()));
406 if (i + 1 < ids.size()) {
407 const int before_y = GetPopupAt(i)->GetBoundsInScreen().y();
408 AnimateToMiddle();
409 EXPECT_GT(before_y, GetPopupAt(i)->GetBoundsInScreen().y());
410 AnimateToEnd();
411 }
412 }
413 EXPECT_FALSE(IsAnimating());
414
415 EXPECT_EQ(kMaxVisiblePopupNotifications, GetPopupCounts());
416
417 for (size_t i = 0; i < ids.size(); ++i)
418 EXPECT_EQ(ids[i], GetPopupAt(i)->id());
419
420 for (size_t i = 0; i < ids.size() - 1; ++i) {
421 EXPECT_GT(GetPopupAt(i + 1)->GetBoundsInScreen().x(),
422 GetPopupAt(i)->GetBoundsInScreen().bottom());
423 }
424 }
425
TEST_F(MessagePopupCollectionTest,UpdateContents)426 TEST_F(MessagePopupCollectionTest, UpdateContents) {
427 std::string id = AddNotification();
428 AnimateToEnd();
429 EXPECT_FALSE(IsAnimating());
430 EXPECT_EQ(1u, GetPopupCounts());
431 EXPECT_FALSE(GetPopup(id)->updated());
432
433 auto updated_notification = CreateNotification(id);
434 updated_notification->set_message(base::ASCIIToUTF16("updated"));
435 MessageCenter::Get()->UpdateNotification(id, std::move(updated_notification));
436 EXPECT_EQ(1u, GetPopupCounts());
437 EXPECT_TRUE(GetPopup(id)->updated());
438 }
439
440 // Failiing on MacOS 10.10. https://crbug.com/1047503
441 #if defined(OS_APPLE)
442 #define MAYBE_UpdateContentsCausesPopupClose \
443 DISABLED_UpdateContentsCausesPopupClose
444 #else
445 #define MAYBE_UpdateContentsCausesPopupClose UpdateContentsCausesPopupClose
446 #endif
TEST_F(MessagePopupCollectionTest,MAYBE_UpdateContentsCausesPopupClose)447 TEST_F(MessagePopupCollectionTest, MAYBE_UpdateContentsCausesPopupClose) {
448 std::string id = AddNotification();
449 AnimateToEnd();
450 RunPendingMessages();
451 EXPECT_FALSE(IsAnimating());
452 EXPECT_EQ(1u, GetPopupCounts());
453 EXPECT_FALSE(GetPopup(id)->updated());
454
455 GetPopup(id)->set_height_after_update(2048);
456
457 auto updated_notification = CreateNotification(id);
458 updated_notification->set_message(base::ASCIIToUTF16("updated"));
459 MessageCenter::Get()->UpdateNotification(id, std::move(updated_notification));
460 RunPendingMessages();
461 EXPECT_EQ(0u, GetPopupCounts());
462 }
463
TEST_F(MessagePopupCollectionTest,MessageCenterVisibility)464 TEST_F(MessagePopupCollectionTest, MessageCenterVisibility) {
465 // It only applies to a platform with MessageCenterView i.e. Chrome OS.
466 MessageCenter::Get()->SetHasMessageCenterView(true);
467
468 for (size_t i = 0; i < kMaxVisiblePopupNotifications; ++i)
469 AddNotification();
470 AnimateUntilIdle();
471
472 EXPECT_EQ(kMaxVisiblePopupNotifications, GetPopupCounts());
473
474 EXPECT_EQ(3u, GetPopupCounts());
475 EXPECT_EQ(3u, MessageCenter::Get()->GetPopupNotifications().size());
476
477 // The notification should be hidden when MessageCenterView is visible.
478 MessageCenter::Get()->SetVisibility(Visibility::VISIBILITY_MESSAGE_CENTER);
479 // It should not animate in order to show ARC++ notifications properly.
480 EXPECT_FALSE(IsAnimating());
481
482 MessageCenter::Get()->SetVisibility(Visibility::VISIBILITY_TRANSIENT);
483 EXPECT_FALSE(IsAnimating());
484 EXPECT_EQ(0u, GetPopupCounts());
485 EXPECT_EQ(0u, MessageCenter::Get()->GetPopupNotifications().size());
486 }
487
TEST_F(MessagePopupCollectionTest,ShowCustomOnPrimaryDisplay)488 TEST_F(MessagePopupCollectionTest, ShowCustomOnPrimaryDisplay) {
489 // TODO(yoshiki): Support custom popup notification on multiple display
490 // (crbug.com/715370).
491 popup_collection()->set_is_primary_display(true);
492 auto custom = CreateNotification("id");
493 custom->set_type(NOTIFICATION_TYPE_CUSTOM);
494 MessageCenter::Get()->AddNotification(std::move(custom));
495 EXPECT_TRUE(IsAnimating());
496 EXPECT_EQ(1u, GetPopupCounts());
497 }
498
TEST_F(MessagePopupCollectionTest,NotShowCustomOnSubDisplay)499 TEST_F(MessagePopupCollectionTest, NotShowCustomOnSubDisplay) {
500 // Disables popup of custom notification on non-primary displays, since
501 // currently custom notification supports only on one display at the same
502 // time.
503 // TODO(yoshiki): Support custom popup notification on multiple display
504 // (crbug.com/715370).
505
506 popup_collection()->set_is_primary_display(false);
507 auto custom = CreateNotification("id");
508 custom->set_type(NOTIFICATION_TYPE_CUSTOM);
509 MessageCenter::Get()->AddNotification(std::move(custom));
510 EXPECT_FALSE(IsAnimating());
511 EXPECT_EQ(0u, GetPopupCounts());
512 }
513
TEST_F(MessagePopupCollectionTest,MixedFullscreenShow)514 TEST_F(MessagePopupCollectionTest, MixedFullscreenShow) {
515 popup_collection()->set_is_fullscreen(false);
516 AddNotification();
517 EXPECT_TRUE(IsAnimating());
518 EXPECT_EQ(1u, GetPopupCounts());
519 }
520
TEST_F(MessagePopupCollectionTest,MixedFullscreenBlock)521 TEST_F(MessagePopupCollectionTest, MixedFullscreenBlock) {
522 popup_collection()->set_is_fullscreen(true);
523 AddNotification();
524 EXPECT_FALSE(IsAnimating());
525 EXPECT_EQ(0u, GetPopupCounts());
526 }
527
TEST_F(MessagePopupCollectionTest,NotificationsMoveDown)528 TEST_F(MessagePopupCollectionTest, NotificationsMoveDown) {
529 std::vector<std::string> ids;
530 for (size_t i = 0; i < kMaxVisiblePopupNotifications + 1; ++i)
531 ids.push_back(AddNotification());
532
533 AnimateUntilIdle();
534
535 EXPECT_EQ(kMaxVisiblePopupNotifications, GetPopupCounts());
536 EXPECT_FALSE(IsAnimating());
537
538 gfx::Rect dismissed = GetPopup(ids.front())->GetBoundsInScreen();
539
540 MessageCenter::Get()->MarkSinglePopupAsShown(ids.front(), false);
541 EXPECT_TRUE(IsAnimating());
542
543 AnimateToMiddle();
544 EXPECT_GT(1.0f, GetPopup(ids[0])->GetOpacity());
545 EXPECT_EQ(ids[0], GetPopup(ids[0])->id());
546
547 AnimateToEnd();
548 EXPECT_EQ(ids[1], GetPopup(ids[1])->id());
549 EXPECT_TRUE(IsAnimating());
550
551 gfx::Rect before = GetPopup(ids[1])->GetBoundsInScreen();
552
553 AnimateToMiddle();
554 gfx::Rect moving = GetPopup(ids[1])->GetBoundsInScreen();
555 EXPECT_GT(moving.bottom(), before.bottom());
556 EXPECT_GT(dismissed.bottom(), moving.bottom());
557
558 AnimateToEnd();
559 gfx::Rect after = GetPopup(ids[1])->GetBoundsInScreen();
560 EXPECT_EQ(dismissed, after);
561 EXPECT_EQ(kMaxVisiblePopupNotifications, GetPopupCounts());
562 EXPECT_TRUE(IsAnimating());
563
564 EXPECT_EQ(0.f, GetPopup(ids.back())->GetOpacity());
565
566 AnimateToMiddle();
567 EXPECT_LT(0.0f, GetPopup(ids.back())->GetOpacity());
568
569 AnimateToEnd();
570 EXPECT_EQ(1.0f, GetPopup(ids.back())->GetOpacity());
571 EXPECT_FALSE(IsAnimating());
572 }
573
TEST_F(MessagePopupCollectionTest,NotificationsMoveDownInverse)574 TEST_F(MessagePopupCollectionTest, NotificationsMoveDownInverse) {
575 popup_collection()->set_inverse();
576
577 std::vector<std::string> ids;
578 for (size_t i = 0; i < kMaxVisiblePopupNotifications; ++i)
579 ids.push_back(AddNotification());
580
581 std::string dismissed_id = ids[kMaxVisiblePopupNotifications - 1];
582 std::string new_bottom_id = ids[kMaxVisiblePopupNotifications - 2];
583
584 AnimateUntilIdle();
585
586 EXPECT_EQ(kMaxVisiblePopupNotifications, GetPopupCounts());
587 EXPECT_FALSE(IsAnimating());
588
589 gfx::Rect dismissed = GetPopup(dismissed_id)->GetBoundsInScreen();
590
591 MessageCenter::Get()->MarkSinglePopupAsShown(dismissed_id, false);
592 EXPECT_TRUE(IsAnimating());
593
594 AnimateToMiddle();
595 EXPECT_GT(1.0f, GetPopup(dismissed_id)->GetOpacity());
596 EXPECT_EQ(dismissed_id, GetPopup(dismissed_id)->id());
597
598 AnimateToEnd();
599 EXPECT_EQ(ids[1], GetPopup(new_bottom_id)->id());
600 EXPECT_TRUE(IsAnimating());
601
602 gfx::Rect before = GetPopup(new_bottom_id)->GetBoundsInScreen();
603
604 AnimateToMiddle();
605 gfx::Rect moving = GetPopup(new_bottom_id)->GetBoundsInScreen();
606 EXPECT_GT(moving.bottom(), before.bottom());
607 EXPECT_GT(dismissed.bottom(), moving.bottom());
608
609 AnimateToEnd();
610 gfx::Rect after = GetPopup(new_bottom_id)->GetBoundsInScreen();
611 EXPECT_EQ(dismissed, after);
612 EXPECT_EQ(kMaxVisiblePopupNotifications - 1, GetPopupCounts());
613 EXPECT_FALSE(IsAnimating());
614 }
615
TEST_F(MessagePopupCollectionTest,NotificationsMoveUpForInverse)616 TEST_F(MessagePopupCollectionTest, NotificationsMoveUpForInverse) {
617 popup_collection()->set_inverse();
618
619 std::vector<std::string> ids;
620 for (size_t i = 0; i < kMaxVisiblePopupNotifications + 1; ++i)
621 ids.push_back(AddNotification());
622
623 AnimateUntilIdle();
624
625 EXPECT_EQ(kMaxVisiblePopupNotifications, GetPopupCounts());
626 EXPECT_FALSE(IsAnimating());
627
628 gfx::Rect dismissed = GetPopup(ids.front())->GetBoundsInScreen();
629
630 MessageCenter::Get()->MarkSinglePopupAsShown(ids.front(), false);
631 EXPECT_TRUE(IsAnimating());
632
633 // FADE_OUT
634 AnimateToMiddle();
635 EXPECT_GT(1.0f, GetPopup(ids[0])->GetOpacity());
636 EXPECT_EQ(ids[0], GetPopup(ids[0])->id());
637
638 AnimateToEnd();
639 EXPECT_EQ(ids[1], GetPopup(ids[1])->id());
640 EXPECT_TRUE(IsAnimating());
641
642 gfx::Rect before = GetPopup(ids[1])->GetBoundsInScreen();
643
644 // MOVE_UP_FOR_INVERSE
645 AnimateToMiddle();
646 gfx::Rect moving = GetPopup(ids[1])->GetBoundsInScreen();
647 EXPECT_LT(moving.bottom(), before.bottom());
648 EXPECT_LT(dismissed.bottom(), moving.bottom());
649
650 AnimateToEnd();
651 gfx::Rect after = GetPopup(ids[1])->GetBoundsInScreen();
652 EXPECT_EQ(dismissed, after);
653 EXPECT_EQ(kMaxVisiblePopupNotifications, GetPopupCounts());
654 EXPECT_TRUE(IsAnimating());
655
656 EXPECT_EQ(0.f, GetPopup(ids.back())->GetOpacity());
657
658 // FADE_IN
659 AnimateToMiddle();
660 EXPECT_LT(0.0f, GetPopup(ids.back())->GetOpacity());
661
662 AnimateToEnd();
663 EXPECT_EQ(1.0f, GetPopup(ids.back())->GetOpacity());
664 EXPECT_FALSE(IsAnimating());
665 }
666
TEST_F(MessagePopupCollectionTest,PopupResized)667 TEST_F(MessagePopupCollectionTest, PopupResized) {
668 std::vector<std::string> ids;
669 for (size_t i = 0; i < kMaxVisiblePopupNotifications; ++i)
670 ids.push_back(AddNotification());
671 AnimateUntilIdle();
672
673 std::vector<gfx::Rect> previous_bounds;
674 for (const auto& id : ids)
675 previous_bounds.push_back(GetPopup(id)->GetBoundsInScreen());
676
677 const int changed_height = 256;
678 GetPopup(ids[1])->SetPreferredHeight(changed_height);
679
680 EXPECT_TRUE(IsAnimating());
681
682 AnimateToMiddle();
683 EXPECT_EQ(previous_bounds[0], GetPopup(ids[0])->GetBoundsInScreen());
684 EXPECT_EQ(previous_bounds[1].bottom(),
685 GetPopup(ids[1])->GetBoundsInScreen().bottom());
686 EXPECT_GT(previous_bounds[1].y(), GetPopup(ids[1])->GetBoundsInScreen().y());
687 EXPECT_GT(previous_bounds[2].bottom(),
688 GetPopup(ids[2])->GetBoundsInScreen().bottom());
689 EXPECT_GT(previous_bounds[2].y(), GetPopup(ids[2])->GetBoundsInScreen().y());
690
691 AnimateToEnd();
692 EXPECT_FALSE(IsAnimating());
693 EXPECT_EQ(previous_bounds[0], GetPopup(ids[0])->GetBoundsInScreen());
694 EXPECT_EQ(changed_height, GetPopup(ids[1])->GetBoundsInScreen().height());
695 }
696
TEST_F(MessagePopupCollectionTest,ExpandLatest)697 TEST_F(MessagePopupCollectionTest, ExpandLatest) {
698 std::string id = AddNotification();
699 AnimateToEnd();
700 GetPopup(id)->set_expandable(true);
701 const int top_y = GetPopup(id)->GetBoundsInScreen().y();
702
703 AddNotification();
704 EXPECT_TRUE(IsAnimating());
705 EXPECT_EQ(1u, GetPopupCounts());
706 AnimateToMiddle();
707 EXPECT_LT(top_y, GetPopup(id)->GetBoundsInScreen().y());
708 AnimateToEnd();
709 EXPECT_LT(top_y, GetPopup(id)->GetBoundsInScreen().y());
710
711 EXPECT_TRUE(IsAnimating());
712 EXPECT_EQ(2u, GetPopupCounts());
713 AnimateToEnd();
714 EXPECT_FALSE(IsAnimating());
715 }
716
TEST_F(MessagePopupCollectionTest,ExpandLatestWithMoveDown)717 TEST_F(MessagePopupCollectionTest, ExpandLatestWithMoveDown) {
718 std::vector<std::string> ids;
719 for (size_t i = 0; i < kMaxVisiblePopupNotifications + 1; ++i)
720 ids.push_back(AddNotification());
721
722 AnimateUntilIdle();
723 EXPECT_EQ(kMaxVisiblePopupNotifications, GetPopupCounts());
724
725 GetPopup(ids[1])->set_expandable(true);
726
727 const int top_y = GetPopup(ids[1])->GetBoundsInScreen().y();
728
729 MessageCenter::Get()->MarkSinglePopupAsShown(ids.front(), false);
730 AnimateToEnd();
731 EXPECT_TRUE(IsAnimating());
732 EXPECT_EQ(kMaxVisiblePopupNotifications - 1, GetPopupCounts());
733
734 AnimateToMiddle();
735 EXPECT_LT(top_y, GetPopup(ids[2])->GetBoundsInScreen().y());
736 AnimateToEnd();
737 EXPECT_EQ(kMaxVisiblePopupNotifications, GetPopupCounts());
738 EXPECT_TRUE(IsAnimating());
739 AnimateToEnd();
740 EXPECT_FALSE(IsAnimating());
741 }
742
TEST_F(MessagePopupCollectionTest,HoverClose)743 TEST_F(MessagePopupCollectionTest, HoverClose) {
744 std::string id0 = AddNotification();
745 AnimateToEnd();
746 popup_collection()->set_new_popup_height(256);
747 std::string id1 = AddNotification();
748 AnimateToEnd();
749 popup_collection()->set_new_popup_height(84);
750 std::string id2 = AddNotification();
751 AnimateToEnd();
752 EXPECT_FALSE(IsAnimating());
753
754 EXPECT_TRUE(IsPopupTimerStarted());
755 GetPopup(id0)->SetHovered(true);
756 EXPECT_FALSE(IsPopupTimerStarted());
757
758 const int first_popup_top = GetPopup(id0)->GetBoundsInScreen().y();
759
760 MessageCenter::Get()->RemoveNotification(id0, true);
761 EXPECT_TRUE(IsAnimating());
762 AnimateToEnd();
763 EXPECT_TRUE(IsAnimating());
764 AnimateToMiddle();
765 GetPopup(id1)->SetHovered(true);
766 AnimateToEnd();
767 EXPECT_FALSE(IsAnimating());
768 EXPECT_EQ(first_popup_top, GetPopup(id1)->GetBoundsInScreen().y());
769
770 EXPECT_FALSE(IsPopupTimerStarted());
771 GetPopup(id1)->SetHovered(false);
772 EXPECT_TRUE(IsAnimating());
773 AnimateToEnd();
774 EXPECT_FALSE(IsAnimating());
775 EXPECT_TRUE(IsPopupTimerStarted());
776 EXPECT_GT(first_popup_top, GetPopup(id1)->GetBoundsInScreen().y());
777 }
778
TEST_F(MessagePopupCollectionTest,ActivatedClose)779 TEST_F(MessagePopupCollectionTest, ActivatedClose) {
780 std::string id0 = AddNotification();
781 AnimateToEnd();
782 popup_collection()->set_new_popup_height(256);
783 std::string id1 = AddNotification();
784 AnimateToEnd();
785 popup_collection()->set_new_popup_height(84);
786 std::string id2 = AddNotification();
787 AnimateToEnd();
788 EXPECT_FALSE(IsAnimating());
789
790 EXPECT_TRUE(IsPopupTimerStarted());
791 GetPopup(id0)->Activate();
792 EXPECT_FALSE(IsPopupTimerStarted());
793
794 const int first_popup_top = GetPopup(id0)->GetBoundsInScreen().y();
795
796 MessageCenter::Get()->RemoveNotification(id0, true);
797 AnimateToEnd();
798 AnimateToEnd();
799 EXPECT_FALSE(IsAnimating());
800 EXPECT_GT(first_popup_top, GetPopup(id1)->GetBoundsInScreen().y());
801 EXPECT_TRUE(IsPopupTimerStarted());
802 }
803
TEST_F(MessagePopupCollectionTest,SlideOutClose)804 TEST_F(MessagePopupCollectionTest, SlideOutClose) {
805 std::vector<std::string> ids;
806 for (size_t i = 0; i < kMaxVisiblePopupNotifications; ++i)
807 ids.push_back(AddNotification());
808
809 AnimateUntilIdle();
810
811 GetPopup(ids[1])->SetOpacity(0);
812 MessageCenter::Get()->RemoveNotification(ids[1], true);
813 AnimateToEnd();
814
815 EXPECT_FALSE(IsAnimating());
816 EXPECT_TRUE(IsPopupTimerStarted());
817 }
818
TEST_F(MessagePopupCollectionTest,TooTallNotification)819 TEST_F(MessagePopupCollectionTest, TooTallNotification) {
820 SetDisplayInfo(gfx::Rect(0, 0, 800, 470), // taskbar at the bottom.
821 gfx::Rect(0, 0, 800, 480));
822
823 std::string id0 = AddNotification();
824 std::string id1 = AddNotification();
825
826 AnimateUntilIdle();
827
828 EXPECT_EQ(2u, GetPopupCounts());
829
830 popup_collection()->set_new_popup_height(400);
831 std::string id2 = AddNotification();
832
833 EXPECT_FALSE(IsAnimating());
834 EXPECT_EQ(2u, GetPopupCounts());
835 EXPECT_TRUE(GetPopup(id0));
836 EXPECT_TRUE(GetPopup(id1));
837 EXPECT_FALSE(GetPopup(id2));
838
839 MessageCenter::Get()->MarkSinglePopupAsShown(id0, false);
840 AnimateUntilIdle();
841 EXPECT_EQ(1u, GetPopupCounts());
842 EXPECT_FALSE(GetPopup(id2));
843
844 MessageCenter::Get()->MarkSinglePopupAsShown(id1, false);
845 AnimateUntilIdle();
846 EXPECT_EQ(1u, GetPopupCounts());
847 EXPECT_TRUE(GetPopup(id2));
848 }
849
TEST_F(MessagePopupCollectionTest,TooTallNotificationInverse)850 TEST_F(MessagePopupCollectionTest, TooTallNotificationInverse) {
851 popup_collection()->set_inverse();
852
853 SetDisplayInfo(gfx::Rect(0, 0, 800, 470), // taskbar at the bottom.
854 gfx::Rect(0, 0, 800, 480));
855
856 // 2 popus shall fit. 3 popups shall not.
857 popup_collection()->set_new_popup_height(200);
858
859 std::string id0 = AddNotification();
860 std::string id1 = AddNotification();
861
862 AnimateUntilIdle();
863
864 EXPECT_EQ(2u, GetPopupCounts());
865
866 std::string id2 = AddNotification();
867
868 EXPECT_FALSE(IsAnimating());
869 EXPECT_EQ(2u, GetPopupCounts());
870 EXPECT_TRUE(GetPopup(id0));
871 EXPECT_TRUE(GetPopup(id1));
872 EXPECT_FALSE(GetPopup(id2));
873
874 MessageCenter::Get()->MarkSinglePopupAsShown(id0, false);
875 AnimateUntilIdle();
876 EXPECT_EQ(2u, GetPopupCounts());
877 EXPECT_FALSE(GetPopup(id0));
878 EXPECT_TRUE(GetPopup(id1));
879 EXPECT_TRUE(GetPopup(id2));
880 }
881
TEST_F(MessagePopupCollectionTest,DisplaySizeChanged)882 TEST_F(MessagePopupCollectionTest, DisplaySizeChanged) {
883 std::string id0 = AddNotification();
884 AnimateToEnd();
885 std::string id1 = AddNotification();
886 AnimateToEnd();
887 popup_collection()->set_new_popup_height(400);
888 std::string id2 = AddNotification();
889 AnimateToEnd();
890 EXPECT_FALSE(IsAnimating());
891
892 EXPECT_TRUE(GetPopup(id0));
893 EXPECT_TRUE(GetPopup(id1));
894 EXPECT_TRUE(GetPopup(id2));
895
896 SetDisplayInfo(gfx::Rect(0, 0, 800, 470), // taskbar at the bottom.
897 gfx::Rect(0, 0, 800, 480));
898 popup_collection()->ResetBounds();
899
900 EXPECT_TRUE(GetPopup(id0));
901 EXPECT_TRUE(work_area().Contains(GetPopup(id0)->GetBoundsInScreen()));
902 EXPECT_TRUE(GetPopup(id1));
903 EXPECT_TRUE(work_area().Contains(GetPopup(id1)->GetBoundsInScreen()));
904 EXPECT_FALSE(GetPopup(id2));
905
906 MessageCenter::Get()->MarkSinglePopupAsShown(id0, false);
907 MessageCenter::Get()->MarkSinglePopupAsShown(id1, false);
908 AnimateUntilIdle();
909 EXPECT_EQ(1u, GetPopupCounts());
910 EXPECT_TRUE(GetPopup(id2));
911 }
912
TEST_F(MessagePopupCollectionTest,PopupResizedAndOverflown)913 TEST_F(MessagePopupCollectionTest, PopupResizedAndOverflown) {
914 SetDisplayInfo(gfx::Rect(0, 0, 800, 470), // taskbar at the bottom.
915 gfx::Rect(0, 0, 800, 480));
916
917 std::string id0 = AddNotification();
918 std::string id1 = AddNotification();
919 std::string id2 = AddNotification();
920 AnimateUntilIdle();
921
922 EXPECT_TRUE(GetPopup(id0));
923 EXPECT_TRUE(GetPopup(id1));
924 EXPECT_TRUE(GetPopup(id2));
925
926 const int changed_height = 300;
927 GetPopup(id1)->SetPreferredHeight(changed_height);
928
929 AnimateUntilIdle();
930 RunPendingMessages();
931
932 EXPECT_TRUE(GetPopup(id0));
933 EXPECT_TRUE(work_area().Contains(GetPopup(id0)->GetBoundsInScreen()));
934 EXPECT_TRUE(GetPopup(id1));
935 EXPECT_TRUE(work_area().Contains(GetPopup(id1)->GetBoundsInScreen()));
936 EXPECT_FALSE(GetPopup(id2));
937
938 MessageCenter::Get()->MarkSinglePopupAsShown(id0, false);
939 AnimateUntilIdle();
940 EXPECT_EQ(2u, GetPopupCounts());
941 EXPECT_TRUE(GetPopup(id2));
942 }
943
TEST_F(MessagePopupCollectionTest,DismissOnClick)944 TEST_F(MessagePopupCollectionTest, DismissOnClick) {
945 MessageCenter::Get()->SetHasMessageCenterView(true);
946
947 std::string id1 = AddNotification();
948 std::string id2 = AddNotification();
949
950 AnimateUntilIdle();
951
952 EXPECT_EQ(2u, GetPopupCounts());
953 EXPECT_TRUE(GetPopup(id1));
954 EXPECT_TRUE(GetPopup(id2));
955
956 MessageCenter::Get()->ClickOnNotification(id2);
957 AnimateUntilIdle();
958
959 EXPECT_EQ(1u, GetPopupCounts());
960 EXPECT_TRUE(GetPopup(id1));
961 EXPECT_FALSE(GetPopup(id2));
962
963 MessageCenter::Get()->ClickOnNotificationButton(id1, 0);
964 AnimateUntilIdle();
965
966 EXPECT_EQ(0u, GetPopupCounts());
967 EXPECT_FALSE(GetPopup(id1));
968 EXPECT_FALSE(GetPopup(id2));
969 }
970
TEST_F(MessagePopupCollectionTest,NotDismissedOnClick)971 TEST_F(MessagePopupCollectionTest, NotDismissedOnClick) {
972 MessageCenter::Get()->SetHasMessageCenterView(false);
973
974 std::string id1 = AddNotification();
975 std::string id2 = AddNotification();
976
977 AnimateUntilIdle();
978
979 EXPECT_EQ(2u, GetPopupCounts());
980 EXPECT_TRUE(GetPopup(id1));
981 EXPECT_TRUE(GetPopup(id2));
982
983 MessageCenter::Get()->ClickOnNotification(id2);
984 AnimateUntilIdle();
985
986 EXPECT_EQ(2u, GetPopupCounts());
987 EXPECT_TRUE(GetPopup(id1));
988 EXPECT_TRUE(GetPopup(id2));
989
990 MessageCenter::Get()->ClickOnNotificationButton(id1, 0);
991 AnimateUntilIdle();
992
993 EXPECT_EQ(2u, GetPopupCounts());
994 EXPECT_TRUE(GetPopup(id1));
995 EXPECT_TRUE(GetPopup(id2));
996 }
997
TEST_F(MessagePopupCollectionTest,DefaultPositioning)998 TEST_F(MessagePopupCollectionTest, DefaultPositioning) {
999 std::string id0 = AddNotification();
1000 std::string id1 = AddNotification();
1001 std::string id2 = AddNotification();
1002 std::string id3 = AddNotification();
1003
1004 AnimateUntilIdle();
1005
1006 gfx::Rect r0 = GetPopup(id0)->GetBoundsInScreen();
1007 gfx::Rect r1 = GetPopup(id1)->GetBoundsInScreen();
1008 gfx::Rect r2 = GetPopup(id2)->GetBoundsInScreen();
1009
1010 // The 4th toast is not shown yet.
1011 EXPECT_FALSE(GetPopup(id3));
1012
1013 // 3 toasts are shown, equal size, vertical stack.
1014 EXPECT_EQ(r0.width(), r1.width());
1015 EXPECT_EQ(r1.width(), r2.width());
1016
1017 EXPECT_EQ(r0.height(), r1.height());
1018 EXPECT_EQ(r1.height(), r2.height());
1019
1020 EXPECT_GT(r0.y(), r1.y());
1021 EXPECT_GT(r1.y(), r2.y());
1022
1023 EXPECT_EQ(r0.x(), r1.x());
1024 EXPECT_EQ(r1.x(), r2.x());
1025 }
1026
TEST_F(MessagePopupCollectionTest,DefaultPositioningInverse)1027 TEST_F(MessagePopupCollectionTest, DefaultPositioningInverse) {
1028 popup_collection()->set_inverse();
1029
1030 std::string id0 = AddNotification();
1031 std::string id1 = AddNotification();
1032 std::string id2 = AddNotification();
1033 std::string id3 = AddNotification();
1034
1035 AnimateUntilIdle();
1036
1037 // This part is inverted.
1038 gfx::Rect r0 = GetPopup(id2)->GetBoundsInScreen();
1039 gfx::Rect r1 = GetPopup(id1)->GetBoundsInScreen();
1040 gfx::Rect r2 = GetPopup(id0)->GetBoundsInScreen();
1041
1042 // The 4th toast is not shown yet.
1043 EXPECT_FALSE(GetPopup(id3));
1044
1045 // 3 toasts are shown, equal size, vertical stack.
1046 EXPECT_EQ(r0.width(), r1.width());
1047 EXPECT_EQ(r1.width(), r2.width());
1048
1049 EXPECT_EQ(r0.height(), r1.height());
1050 EXPECT_EQ(r1.height(), r2.height());
1051
1052 EXPECT_GT(r0.y(), r1.y());
1053 EXPECT_GT(r1.y(), r2.y());
1054
1055 EXPECT_EQ(r0.x(), r1.x());
1056 EXPECT_EQ(r1.x(), r2.x());
1057 }
1058
TEST_F(MessagePopupCollectionTest,DefaultPositioningWithRightTaskbar)1059 TEST_F(MessagePopupCollectionTest, DefaultPositioningWithRightTaskbar) {
1060 // If taskbar is on the right we show the toasts bottom to top as usual.
1061
1062 // Simulate a taskbar at the right.
1063 SetDisplayInfo(gfx::Rect(0, 0, 590, 400), // Work-area.
1064 gfx::Rect(0, 0, 600, 400)); // Display-bounds.
1065 std::string id0 = AddNotification();
1066 std::string id1 = AddNotification();
1067
1068 AnimateUntilIdle();
1069
1070 gfx::Rect r0 = GetPopup(id0)->GetBoundsInScreen();
1071 gfx::Rect r1 = GetPopup(id1)->GetBoundsInScreen();
1072
1073 // 2 toasts are shown, equal size, vertical stack.
1074 EXPECT_EQ(r0.width(), r1.width());
1075 EXPECT_EQ(r0.height(), r1.height());
1076 EXPECT_GT(r0.y(), r1.y());
1077 EXPECT_EQ(r0.x(), r1.x());
1078 }
1079
TEST_F(MessagePopupCollectionTest,TopDownPositioningWithTopTaskbar)1080 TEST_F(MessagePopupCollectionTest, TopDownPositioningWithTopTaskbar) {
1081 // Simulate a taskbar at the top.
1082 SetDisplayInfo(gfx::Rect(0, 10, 600, 390), // Work-area.
1083 gfx::Rect(0, 0, 600, 400)); // Display-bounds.
1084 std::string id0 = AddNotification();
1085 std::string id1 = AddNotification();
1086
1087 AnimateUntilIdle();
1088
1089 gfx::Rect r0 = GetPopup(id0)->GetBoundsInScreen();
1090 gfx::Rect r1 = GetPopup(id1)->GetBoundsInScreen();
1091
1092 // 2 toasts are shown, equal size, vertical stack.
1093 EXPECT_EQ(r0.width(), r1.width());
1094 EXPECT_EQ(r0.height(), r1.height());
1095 EXPECT_LT(r0.y(), r1.y());
1096 EXPECT_EQ(r0.x(), r1.x());
1097 }
1098
TEST_F(MessagePopupCollectionTest,TopDownPositioningWithLeftAndTopTaskbar)1099 TEST_F(MessagePopupCollectionTest, TopDownPositioningWithLeftAndTopTaskbar) {
1100 // If there "seems" to be a taskbar on left and top (like in Unity), it is
1101 // assumed that the actual taskbar is the top one.
1102
1103 // Simulate a taskbar at the top and left.
1104 SetDisplayInfo(gfx::Rect(10, 10, 590, 390), // Work-area.
1105 gfx::Rect(0, 0, 600, 400)); // Display-bounds.
1106 std::string id0 = AddNotification();
1107 std::string id1 = AddNotification();
1108
1109 AnimateUntilIdle();
1110
1111 gfx::Rect r0 = GetPopup(id0)->GetBoundsInScreen();
1112 gfx::Rect r1 = GetPopup(id1)->GetBoundsInScreen();
1113
1114 // 2 toasts are shown, equal size, vertical stack.
1115 EXPECT_EQ(r0.width(), r1.width());
1116 EXPECT_EQ(r0.height(), r1.height());
1117 EXPECT_LT(r0.y(), r1.y());
1118 EXPECT_EQ(r0.x(), r1.x());
1119 }
1120
TEST_F(MessagePopupCollectionTest,TopDownPositioningWithBottomAndTopTaskbar)1121 TEST_F(MessagePopupCollectionTest, TopDownPositioningWithBottomAndTopTaskbar) {
1122 // If there "seems" to be a taskbar on bottom and top (like in Gnome), it is
1123 // assumed that the actual taskbar is the top one.
1124
1125 // Simulate a taskbar at the top and bottom.
1126 SetDisplayInfo(gfx::Rect(0, 10, 580, 400), // Work-area.
1127 gfx::Rect(0, 0, 600, 400)); // Display-bounds.
1128 std::string id0 = AddNotification();
1129 std::string id1 = AddNotification();
1130
1131 AnimateUntilIdle();
1132
1133 gfx::Rect r0 = GetPopup(id0)->GetBoundsInScreen();
1134 gfx::Rect r1 = GetPopup(id1)->GetBoundsInScreen();
1135
1136 // 2 toasts are shown, equal size, vertical stack.
1137 EXPECT_EQ(r0.width(), r1.width());
1138 EXPECT_EQ(r0.height(), r1.height());
1139 EXPECT_LT(r0.y(), r1.y());
1140 EXPECT_EQ(r0.x(), r1.x());
1141 }
1142
TEST_F(MessagePopupCollectionTest,LeftPositioningWithLeftTaskbar)1143 TEST_F(MessagePopupCollectionTest, LeftPositioningWithLeftTaskbar) {
1144 // Simulate a taskbar at the left.
1145 SetDisplayInfo(gfx::Rect(10, 0, 590, 400), // Work-area.
1146 gfx::Rect(0, 0, 600, 400)); // Display-bounds.
1147 std::string id0 = AddNotification();
1148 std::string id1 = AddNotification();
1149
1150 AnimateUntilIdle();
1151
1152 gfx::Rect r0 = GetPopup(id0)->GetBoundsInScreen();
1153 gfx::Rect r1 = GetPopup(id1)->GetBoundsInScreen();
1154
1155 EXPECT_EQ(r0.width(), r1.width());
1156 EXPECT_EQ(r0.height(), r1.height());
1157 EXPECT_GT(r0.y(), r1.y());
1158 EXPECT_EQ(r0.x(), r1.x());
1159
1160 // Ensure that toasts are on the left.
1161 EXPECT_LT(r1.x(), work_area().CenterPoint().x());
1162 EXPECT_TRUE(work_area().Contains(r0));
1163 EXPECT_TRUE(work_area().Contains(r1));
1164 }
1165
TEST_F(MessagePopupCollectionTest,PopupWidgetClosedOutsideDuringFadeOut)1166 TEST_F(MessagePopupCollectionTest, PopupWidgetClosedOutsideDuringFadeOut) {
1167 std::string id = AddNotification();
1168 AnimateUntilIdle();
1169
1170 MessageCenter::Get()->MarkSinglePopupAsShown(id, false);
1171 AnimateToMiddle();
1172
1173 // On Windows it might be possible that the widget is closed outside
1174 // MessagePopupCollection? https://crbug.com/871199
1175 GetPopup(id)->GetWidget()->CloseNow();
1176 AnimateToEnd();
1177
1178 EXPECT_FALSE(IsAnimating());
1179 }
1180
1181 // Notification removing may occur while the animation triggered by the previous
1182 // operation is running. As result, notification is removed from the message
1183 // center but its popup is still kept. At this moment, a new notification with
1184 // the same notification id may be added to the message center. This can happen
1185 // on Chrome OS when an external display is connected with the Chromebook device
1186 // (see https://crbug.com/921402). This test case emulates the procedure of
1187 // the external display connection that is mentioned in the link above. Verifies
1188 // that under this circumstance the notification popup is updated.
TEST_F(MessagePopupCollectionTest,RemoveNotificationWhileAnimating)1189 TEST_F(MessagePopupCollectionTest, RemoveNotificationWhileAnimating) {
1190 const std::string notification_id("test_id");
1191 const std::string old_notification_title("old_title");
1192 const std::string new_notification_title("new_title");
1193
1194 // Create a notification and add it to message center.
1195 auto old_notification =
1196 CreateNotification(notification_id, old_notification_title);
1197 MessageCenter::Get()->AddNotification(std::move(old_notification));
1198 AnimateToMiddle();
1199
1200 // On real device, MessageCenter::RemoveNotification is called before the
1201 // animation ends. As result, notification is removed while popup keeps still.
1202 EXPECT_TRUE(IsAnimating());
1203 MessageCenter::Get()->RemoveNotification(notification_id, false);
1204 EXPECT_FALSE(MessageCenter::Get()->HasPopupNotifications());
1205 EXPECT_EQ(1u, GetPopupCounts());
1206 EXPECT_EQ(old_notification_title, GetPopup(notification_id)->title());
1207
1208 // On real device, the new notification with the same notification id is
1209 // created and added to message center before the animation ends.
1210 auto new_notification =
1211 CreateNotification(notification_id, new_notification_title);
1212 EXPECT_TRUE(IsAnimating());
1213 MessageCenter::Get()->AddNotification(std::move(new_notification));
1214 AnimateUntilIdle();
1215
1216 // Verifies that the new notification popup is shown.
1217 EXPECT_EQ(1u, GetPopupCounts());
1218 EXPECT_EQ(new_notification_title, GetPopup(notification_id)->title());
1219 }
1220
1221 } // namespace message_center
1222