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