Home | History | Annotate | Download | only in message_center
      1 // Copyright (c) 2012 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/notification_list.h"
      6 
      7 #include "base/basictypes.h"
      8 #include "base/i18n/time_formatting.h"
      9 #include "base/strings/stringprintf.h"
     10 #include "base/strings/utf_string_conversions.h"
     11 #include "base/values.h"
     12 #include "testing/gtest/include/gtest/gtest.h"
     13 #include "ui/message_center/message_center_style.h"
     14 #include "ui/message_center/notification_blocker.h"
     15 #include "ui/message_center/notification_types.h"
     16 #include "ui/message_center/notifier_settings.h"
     17 
     18 namespace message_center {
     19 
     20 class NotificationListTest : public testing::Test {
     21  public:
     22   NotificationListTest() {}
     23   virtual ~NotificationListTest() {}
     24 
     25   virtual void SetUp() {
     26     notification_list_.reset(new NotificationList());
     27     counter_ = 0;
     28   }
     29 
     30  protected:
     31   // Currently NotificationListTest doesn't care about some fields like title or
     32   // message, so put a simple template on it. Returns the id of the new
     33   // notification.
     34   std::string AddNotification(
     35       const message_center::RichNotificationData& optional_fields) {
     36     std::string new_id;
     37     scoped_ptr<Notification> notification(
     38         MakeNotification(optional_fields, &new_id));
     39     notification_list_->AddNotification(notification.Pass());
     40     counter_++;
     41     return new_id;
     42   }
     43 
     44   std::string AddNotification() {
     45     return AddNotification(message_center::RichNotificationData());
     46   }
     47 
     48   // Construct a new notification for testing, but don't add it to the list yet.
     49   scoped_ptr<Notification> MakeNotification(
     50       const message_center::RichNotificationData& optional_fields,
     51       std::string* id_out) {
     52     *id_out = base::StringPrintf(kIdFormat, counter_);
     53     scoped_ptr<Notification> notification(new Notification(
     54         message_center::NOTIFICATION_TYPE_SIMPLE,
     55         *id_out,
     56         UTF8ToUTF16(base::StringPrintf(kTitleFormat, counter_)),
     57         UTF8ToUTF16(base::StringPrintf(kMessageFormat, counter_)),
     58         gfx::Image(),
     59         UTF8ToUTF16(kDisplaySource),
     60         NotifierId(NotifierId::APPLICATION, kExtensionId),
     61         optional_fields,
     62         NULL));
     63     return notification.Pass();
     64   }
     65 
     66   scoped_ptr<Notification> MakeNotification(std::string* id_out) {
     67     return MakeNotification(message_center::RichNotificationData(), id_out);
     68   }
     69 
     70   // Utility methods of AddNotification.
     71   std::string AddPriorityNotification(NotificationPriority priority) {
     72     message_center::RichNotificationData optional;
     73     optional.priority = priority;
     74     return AddNotification(optional);
     75   }
     76 
     77   NotificationList::PopupNotifications GetPopups() {
     78     return notification_list()->GetPopupNotifications(blockers_, NULL);
     79   }
     80 
     81   size_t GetPopupCounts() {
     82     return GetPopups().size();
     83   }
     84 
     85   Notification* GetNotification(const std::string& id) {
     86     NotificationList::Notifications::iterator iter =
     87         notification_list()->GetNotification(id);
     88     if (iter == notification_list()->notifications_.end())
     89       return NULL;
     90     return *iter;
     91   }
     92 
     93   NotificationList* notification_list() { return notification_list_.get(); }
     94   const NotificationBlockers& blockers() const { return blockers_; }
     95 
     96   static const char kIdFormat[];
     97   static const char kTitleFormat[];
     98   static const char kMessageFormat[];
     99   static const char kDisplaySource[];
    100   static const char kExtensionId[];
    101 
    102  private:
    103   scoped_ptr<NotificationList> notification_list_;
    104   NotificationBlockers blockers_;
    105   size_t counter_;
    106 
    107   DISALLOW_COPY_AND_ASSIGN(NotificationListTest);
    108 };
    109 
    110 bool IsInNotifications(const NotificationList::Notifications& notifications,
    111                        const std::string& id) {
    112   for (NotificationList::Notifications::const_iterator iter =
    113            notifications.begin(); iter != notifications.end(); ++iter) {
    114     if ((*iter)->id() == id)
    115       return true;
    116   }
    117   return false;
    118 }
    119 
    120 const char NotificationListTest::kIdFormat[] = "id%ld";
    121 const char NotificationListTest::kTitleFormat[] = "id%ld";
    122 const char NotificationListTest::kMessageFormat[] = "message%ld";
    123 const char NotificationListTest::kDisplaySource[] = "source";
    124 const char NotificationListTest::kExtensionId[] = "ext";
    125 
    126 TEST_F(NotificationListTest, Basic) {
    127   ASSERT_EQ(0u, notification_list()->NotificationCount(blockers()));
    128   ASSERT_EQ(0u, notification_list()->UnreadCount(blockers()));
    129 
    130   std::string id0 = AddNotification();
    131   EXPECT_EQ(1u, notification_list()->NotificationCount(blockers()));
    132   std::string id1 = AddNotification();
    133   EXPECT_EQ(2u, notification_list()->NotificationCount(blockers()));
    134   EXPECT_EQ(2u, notification_list()->UnreadCount(blockers()));
    135 
    136   EXPECT_TRUE(notification_list()->HasPopupNotifications(blockers()));
    137   EXPECT_TRUE(notification_list()->HasNotification(id0));
    138   EXPECT_TRUE(notification_list()->HasNotification(id1));
    139   EXPECT_FALSE(notification_list()->HasNotification(id1 + "foo"));
    140 
    141   EXPECT_EQ(2u, GetPopupCounts());
    142 
    143   notification_list()->MarkSinglePopupAsShown(id0, true);
    144   notification_list()->MarkSinglePopupAsShown(id1, true);
    145   EXPECT_EQ(2u, notification_list()->NotificationCount(blockers()));
    146   EXPECT_EQ(0u, GetPopupCounts());
    147 
    148   notification_list()->RemoveNotification(id0);
    149   EXPECT_EQ(1u, notification_list()->NotificationCount(blockers()));
    150   EXPECT_EQ(1u, notification_list()->UnreadCount(blockers()));
    151 
    152   AddNotification();
    153   EXPECT_EQ(2u, notification_list()->NotificationCount(blockers()));
    154 }
    155 
    156 TEST_F(NotificationListTest, MessageCenterVisible) {
    157   AddNotification();
    158   EXPECT_EQ(1u, notification_list()->NotificationCount(blockers()));
    159   ASSERT_EQ(1u, notification_list()->UnreadCount(blockers()));
    160   ASSERT_EQ(1u, GetPopupCounts());
    161 
    162   // Make the message center visible. It resets the unread count and popup
    163   // counts.
    164   notification_list()->SetMessageCenterVisible(true, NULL);
    165   ASSERT_EQ(0u, notification_list()->UnreadCount(blockers()));
    166   ASSERT_EQ(0u, GetPopupCounts());
    167 }
    168 
    169 TEST_F(NotificationListTest, UnreadCount) {
    170   std::string id0 = AddNotification();
    171   std::string id1 = AddNotification();
    172   ASSERT_EQ(2u, notification_list()->UnreadCount(blockers()));
    173 
    174   notification_list()->MarkSinglePopupAsDisplayed(id0);
    175   EXPECT_EQ(1u, notification_list()->UnreadCount(blockers()));
    176   notification_list()->MarkSinglePopupAsDisplayed(id0);
    177   EXPECT_EQ(1u, notification_list()->UnreadCount(blockers()));
    178   notification_list()->MarkSinglePopupAsDisplayed(id1);
    179   EXPECT_EQ(0u, notification_list()->UnreadCount(blockers()));
    180 }
    181 
    182 TEST_F(NotificationListTest, UpdateNotification) {
    183   std::string id0 = AddNotification();
    184   std::string replaced = id0 + "_replaced";
    185   EXPECT_EQ(1u, notification_list()->NotificationCount(blockers()));
    186   scoped_ptr<Notification> notification(
    187       new Notification(message_center::NOTIFICATION_TYPE_SIMPLE,
    188                        replaced,
    189                        UTF8ToUTF16("newtitle"),
    190                        UTF8ToUTF16("newbody"),
    191                        gfx::Image(),
    192                        UTF8ToUTF16(kDisplaySource),
    193                        NotifierId(NotifierId::APPLICATION, kExtensionId),
    194                        message_center::RichNotificationData(),
    195                        NULL));
    196   notification_list()->UpdateNotificationMessage(id0, notification.Pass());
    197   EXPECT_EQ(1u, notification_list()->NotificationCount(blockers()));
    198   const NotificationList::Notifications notifications =
    199       notification_list()->GetVisibleNotifications(blockers());
    200   EXPECT_EQ(replaced, (*notifications.begin())->id());
    201   EXPECT_EQ(UTF8ToUTF16("newtitle"), (*notifications.begin())->title());
    202   EXPECT_EQ(UTF8ToUTF16("newbody"), (*notifications.begin())->message());
    203 }
    204 
    205 TEST_F(NotificationListTest, GetNotificationsByNotifierId) {
    206   NotifierId id0(NotifierId::APPLICATION, "ext0");
    207   NotifierId id1(NotifierId::APPLICATION, "ext1");
    208   NotifierId id2(GURL("http://example.com"));
    209   NotifierId id3(NotifierId::SYSTEM_COMPONENT, "system-notifier");
    210   scoped_ptr<Notification> notification(
    211       new Notification(message_center::NOTIFICATION_TYPE_SIMPLE,
    212                        "id0",
    213                        UTF8ToUTF16("title0"),
    214                        UTF8ToUTF16("message0"),
    215                        gfx::Image(),
    216                        UTF8ToUTF16("source0"),
    217                        id0,
    218                        message_center::RichNotificationData(),
    219                        NULL));
    220   notification_list()->AddNotification(notification.Pass());
    221   notification.reset(new Notification(message_center::NOTIFICATION_TYPE_SIMPLE,
    222                                       "id1",
    223                                       UTF8ToUTF16("title1"),
    224                                       UTF8ToUTF16("message1"),
    225                                       gfx::Image(),
    226                                       UTF8ToUTF16("source0"),
    227                                       id0,
    228                                       message_center::RichNotificationData(),
    229                                       NULL));
    230   notification_list()->AddNotification(notification.Pass());
    231   notification.reset(new Notification(message_center::NOTIFICATION_TYPE_SIMPLE,
    232                                       "id2",
    233                                       UTF8ToUTF16("title1"),
    234                                       UTF8ToUTF16("message1"),
    235                                       gfx::Image(),
    236                                       UTF8ToUTF16("source1"),
    237                                       id0,
    238                                       message_center::RichNotificationData(),
    239                                       NULL));
    240   notification_list()->AddNotification(notification.Pass());
    241   notification.reset(new Notification(message_center::NOTIFICATION_TYPE_SIMPLE,
    242                                       "id3",
    243                                       UTF8ToUTF16("title1"),
    244                                       UTF8ToUTF16("message1"),
    245                                       gfx::Image(),
    246                                       UTF8ToUTF16("source2"),
    247                                       id1,
    248                                       message_center::RichNotificationData(),
    249                                       NULL));
    250   notification_list()->AddNotification(notification.Pass());
    251   notification.reset(new Notification(message_center::NOTIFICATION_TYPE_SIMPLE,
    252                                       "id4",
    253                                       UTF8ToUTF16("title1"),
    254                                       UTF8ToUTF16("message1"),
    255                                       gfx::Image(),
    256                                       UTF8ToUTF16("source2"),
    257                                       id2,
    258                                       message_center::RichNotificationData(),
    259                                       NULL));
    260   notification_list()->AddNotification(notification.Pass());
    261   notification.reset(new Notification(message_center::NOTIFICATION_TYPE_SIMPLE,
    262                                       "id5",
    263                                       UTF8ToUTF16("title1"),
    264                                       UTF8ToUTF16("message1"),
    265                                       gfx::Image(),
    266                                       UTF8ToUTF16("source2"),
    267                                       id3,
    268                                       message_center::RichNotificationData(),
    269                                       NULL));
    270   notification_list()->AddNotification(notification.Pass());
    271 
    272   NotificationList::Notifications by_notifier_id =
    273       notification_list()->GetNotificationsByNotifierId(id0);
    274   EXPECT_TRUE(IsInNotifications(by_notifier_id, "id0"));
    275   EXPECT_TRUE(IsInNotifications(by_notifier_id, "id1"));
    276   EXPECT_TRUE(IsInNotifications(by_notifier_id, "id2"));
    277   EXPECT_FALSE(IsInNotifications(by_notifier_id, "id3"));
    278   EXPECT_FALSE(IsInNotifications(by_notifier_id, "id4"));
    279   EXPECT_FALSE(IsInNotifications(by_notifier_id, "id5"));
    280 
    281   by_notifier_id = notification_list()->GetNotificationsByNotifierId(id1);
    282   EXPECT_FALSE(IsInNotifications(by_notifier_id, "id0"));
    283   EXPECT_FALSE(IsInNotifications(by_notifier_id, "id1"));
    284   EXPECT_FALSE(IsInNotifications(by_notifier_id, "id2"));
    285   EXPECT_TRUE(IsInNotifications(by_notifier_id, "id3"));
    286   EXPECT_FALSE(IsInNotifications(by_notifier_id, "id4"));
    287   EXPECT_FALSE(IsInNotifications(by_notifier_id, "id5"));
    288 
    289   by_notifier_id = notification_list()->GetNotificationsByNotifierId(id2);
    290   EXPECT_FALSE(IsInNotifications(by_notifier_id, "id0"));
    291   EXPECT_FALSE(IsInNotifications(by_notifier_id, "id1"));
    292   EXPECT_FALSE(IsInNotifications(by_notifier_id, "id2"));
    293   EXPECT_FALSE(IsInNotifications(by_notifier_id, "id3"));
    294   EXPECT_TRUE(IsInNotifications(by_notifier_id, "id4"));
    295   EXPECT_FALSE(IsInNotifications(by_notifier_id, "id5"));
    296 
    297   by_notifier_id = notification_list()->GetNotificationsByNotifierId(id3);
    298   EXPECT_FALSE(IsInNotifications(by_notifier_id, "id0"));
    299   EXPECT_FALSE(IsInNotifications(by_notifier_id, "id1"));
    300   EXPECT_FALSE(IsInNotifications(by_notifier_id, "id2"));
    301   EXPECT_FALSE(IsInNotifications(by_notifier_id, "id3"));
    302   EXPECT_FALSE(IsInNotifications(by_notifier_id, "id4"));
    303   EXPECT_TRUE(IsInNotifications(by_notifier_id, "id5"));
    304 }
    305 
    306 TEST_F(NotificationListTest, OldPopupShouldNotBeHidden) {
    307   std::vector<std::string> ids;
    308   for (size_t i = 0; i <= kMaxVisiblePopupNotifications; i++)
    309     ids.push_back(AddNotification());
    310 
    311   NotificationList::PopupNotifications popups = GetPopups();
    312   // The popup should contain the oldest kMaxVisiblePopupNotifications. Newer
    313   // one should come earlier in the popup list. It means, the last element
    314   // of |popups| should be the firstly added one, and so on.
    315   EXPECT_EQ(kMaxVisiblePopupNotifications, popups.size());
    316   NotificationList::PopupNotifications::const_reverse_iterator iter =
    317       popups.rbegin();
    318   for (size_t i = 0; i < kMaxVisiblePopupNotifications; ++i, ++iter) {
    319     EXPECT_EQ(ids[i], (*iter)->id()) << i;
    320   }
    321 
    322   for (NotificationList::PopupNotifications::const_iterator iter =
    323            popups.begin(); iter != popups.end(); ++iter) {
    324     notification_list()->MarkSinglePopupAsShown((*iter)->id(), false);
    325   }
    326   popups.clear();
    327   popups = GetPopups();
    328   EXPECT_EQ(1u, popups.size());
    329   EXPECT_EQ(ids[ids.size() - 1], (*popups.begin())->id());
    330 }
    331 
    332 TEST_F(NotificationListTest, Priority) {
    333   ASSERT_EQ(0u, notification_list()->NotificationCount(blockers()));
    334   ASSERT_EQ(0u, notification_list()->UnreadCount(blockers()));
    335 
    336   // Default priority has the limit on the number of the popups.
    337   for (size_t i = 0; i <= kMaxVisiblePopupNotifications; ++i)
    338     AddNotification();
    339   EXPECT_EQ(kMaxVisiblePopupNotifications + 1,
    340             notification_list()->NotificationCount(blockers()));
    341   EXPECT_EQ(kMaxVisiblePopupNotifications, GetPopupCounts());
    342 
    343   // Low priority: not visible to popups.
    344   notification_list()->SetMessageCenterVisible(true, NULL);
    345   notification_list()->SetMessageCenterVisible(false, NULL);
    346   EXPECT_EQ(0u, notification_list()->UnreadCount(blockers()));
    347   AddPriorityNotification(LOW_PRIORITY);
    348   EXPECT_EQ(kMaxVisiblePopupNotifications + 2,
    349             notification_list()->NotificationCount(blockers()));
    350   EXPECT_EQ(1u, notification_list()->UnreadCount(blockers()));
    351   EXPECT_EQ(0u, GetPopupCounts());
    352 
    353   // Minimum priority: doesn't update the unread count.
    354   AddPriorityNotification(MIN_PRIORITY);
    355   EXPECT_EQ(kMaxVisiblePopupNotifications + 3,
    356             notification_list()->NotificationCount(blockers()));
    357   EXPECT_EQ(1u, notification_list()->UnreadCount(blockers()));
    358   EXPECT_EQ(0u, GetPopupCounts());
    359 
    360   NotificationList::Notifications notifications =
    361       notification_list()->GetVisibleNotifications(blockers());
    362   for (NotificationList::Notifications::const_iterator iter =
    363            notifications.begin(); iter != notifications.end(); ++iter) {
    364     notification_list()->RemoveNotification((*iter)->id());
    365   }
    366 
    367   // Higher priority: no limits to the number of popups.
    368   for (size_t i = 0; i < kMaxVisiblePopupNotifications * 2; ++i)
    369     AddPriorityNotification(HIGH_PRIORITY);
    370   for (size_t i = 0; i < kMaxVisiblePopupNotifications * 2; ++i)
    371     AddPriorityNotification(MAX_PRIORITY);
    372   EXPECT_EQ(kMaxVisiblePopupNotifications * 4,
    373             notification_list()->NotificationCount(blockers()));
    374   EXPECT_EQ(kMaxVisiblePopupNotifications * 4, GetPopupCounts());
    375 }
    376 
    377 TEST_F(NotificationListTest, HasPopupsWithPriority) {
    378   ASSERT_EQ(0u, notification_list()->NotificationCount(blockers()));
    379   ASSERT_EQ(0u, notification_list()->UnreadCount(blockers()));
    380 
    381   AddPriorityNotification(MIN_PRIORITY);
    382   AddPriorityNotification(MAX_PRIORITY);
    383 
    384   EXPECT_EQ(1u, GetPopupCounts());
    385 }
    386 
    387 TEST_F(NotificationListTest, HasPopupsWithSystemPriority) {
    388   ASSERT_EQ(0u, notification_list()->NotificationCount(blockers()));
    389   ASSERT_EQ(0u, notification_list()->UnreadCount(blockers()));
    390 
    391   std::string normal_id = AddPriorityNotification(DEFAULT_PRIORITY);
    392   std::string system_id = AddNotification();
    393   GetNotification(system_id)->SetSystemPriority();
    394 
    395   EXPECT_EQ(2u, GetPopupCounts());
    396 
    397   notification_list()->MarkSinglePopupAsDisplayed(normal_id);
    398   notification_list()->MarkSinglePopupAsDisplayed(system_id);
    399 
    400   notification_list()->MarkSinglePopupAsShown(normal_id, false);
    401   notification_list()->MarkSinglePopupAsShown(system_id, false);
    402 
    403   notification_list()->SetMessageCenterVisible(true, NULL);
    404   notification_list()->SetMessageCenterVisible(false, NULL);
    405   EXPECT_EQ(1u, GetPopupCounts());
    406 
    407   // Mark as read -- emulation of mouse click.
    408   notification_list()->MarkSinglePopupAsShown(system_id, true);
    409   EXPECT_EQ(0u, GetPopupCounts());
    410 }
    411 
    412 TEST_F(NotificationListTest, PriorityPromotion) {
    413   std::string id0 = AddPriorityNotification(LOW_PRIORITY);
    414   std::string replaced = id0 + "_replaced";
    415   EXPECT_EQ(1u, notification_list()->NotificationCount(blockers()));
    416   EXPECT_EQ(0u, GetPopupCounts());
    417   message_center::RichNotificationData optional;
    418   optional.priority = 1;
    419   scoped_ptr<Notification> notification(
    420       new Notification(message_center::NOTIFICATION_TYPE_SIMPLE,
    421                        replaced,
    422                        UTF8ToUTF16("newtitle"),
    423                        UTF8ToUTF16("newbody"),
    424                        gfx::Image(),
    425                        UTF8ToUTF16(kDisplaySource),
    426                        NotifierId(NotifierId::APPLICATION, kExtensionId),
    427                        optional,
    428                        NULL));
    429   notification_list()->UpdateNotificationMessage(id0, notification.Pass());
    430   EXPECT_EQ(1u, notification_list()->NotificationCount(blockers()));
    431   EXPECT_EQ(1u, GetPopupCounts());
    432   const NotificationList::Notifications notifications =
    433       notification_list()->GetVisibleNotifications(blockers());
    434   EXPECT_EQ(replaced, (*notifications.begin())->id());
    435   EXPECT_EQ(UTF8ToUTF16("newtitle"), (*notifications.begin())->title());
    436   EXPECT_EQ(UTF8ToUTF16("newbody"), (*notifications.begin())->message());
    437   EXPECT_EQ(1, (*notifications.begin())->priority());
    438 }
    439 
    440 TEST_F(NotificationListTest, PriorityPromotionWithPopups) {
    441   std::string id0 = AddPriorityNotification(LOW_PRIORITY);
    442   std::string id1 = AddPriorityNotification(DEFAULT_PRIORITY);
    443   EXPECT_EQ(1u, GetPopupCounts());
    444   notification_list()->MarkSinglePopupAsShown(id1, true);
    445   EXPECT_EQ(0u, GetPopupCounts());
    446 
    447   // id0 promoted to LOW->DEFAULT, it'll appear as toast (popup).
    448   message_center::RichNotificationData priority;
    449   priority.priority = DEFAULT_PRIORITY;
    450   scoped_ptr<Notification> notification(
    451       new Notification(message_center::NOTIFICATION_TYPE_SIMPLE,
    452                        id0,
    453                        UTF8ToUTF16("newtitle"),
    454                        UTF8ToUTF16("newbody"),
    455                        gfx::Image(),
    456                        UTF8ToUTF16(kDisplaySource),
    457                        NotifierId(NotifierId::APPLICATION, kExtensionId),
    458                        priority,
    459                        NULL));
    460   notification_list()->UpdateNotificationMessage(id0, notification.Pass());
    461   EXPECT_EQ(1u, GetPopupCounts());
    462   notification_list()->MarkSinglePopupAsShown(id0, true);
    463   EXPECT_EQ(0u, GetPopupCounts());
    464 
    465   // update with no promotion change for id0, it won't appear as a toast.
    466   notification.reset(new Notification(message_center::NOTIFICATION_TYPE_SIMPLE,
    467                                       id0,
    468                                       UTF8ToUTF16("newtitle2"),
    469                                       UTF8ToUTF16("newbody2"),
    470                                       gfx::Image(),
    471                                       UTF8ToUTF16(kDisplaySource),
    472                                       NotifierId(NotifierId::APPLICATION,
    473                                                  kExtensionId),
    474                                       priority,
    475                                       NULL));
    476   notification_list()->UpdateNotificationMessage(id0, notification.Pass());
    477   EXPECT_EQ(0u, GetPopupCounts());
    478 
    479   // id1 promoted to DEFAULT->HIGH, it'll appear as toast (popup).
    480   priority.priority = HIGH_PRIORITY;
    481   notification.reset(new Notification(message_center::NOTIFICATION_TYPE_SIMPLE,
    482                                       id1,
    483                                       UTF8ToUTF16("newtitle"),
    484                                       UTF8ToUTF16("newbody"),
    485                                       gfx::Image(),
    486                                       UTF8ToUTF16(kDisplaySource),
    487                                       NotifierId(NotifierId::APPLICATION,
    488                                                  kExtensionId),
    489                                       priority,
    490                                       NULL));
    491   notification_list()->UpdateNotificationMessage(id1, notification.Pass());
    492   EXPECT_EQ(1u, GetPopupCounts());
    493   notification_list()->MarkSinglePopupAsShown(id1, true);
    494   EXPECT_EQ(0u, GetPopupCounts());
    495 
    496   // id1 promoted to HIGH->MAX, it'll appear as toast again.
    497   priority.priority = MAX_PRIORITY;
    498   notification.reset(new Notification(message_center::NOTIFICATION_TYPE_SIMPLE,
    499                                       id1,
    500                                       UTF8ToUTF16("newtitle2"),
    501                                       UTF8ToUTF16("newbody2"),
    502                                       gfx::Image(),
    503                                       UTF8ToUTF16(kDisplaySource),
    504                                       NotifierId(NotifierId::APPLICATION,
    505                                                  kExtensionId),
    506                                       priority,
    507                                       NULL));
    508   notification_list()->UpdateNotificationMessage(id1, notification.Pass());
    509   EXPECT_EQ(1u, GetPopupCounts());
    510   notification_list()->MarkSinglePopupAsShown(id1, true);
    511   EXPECT_EQ(0u, GetPopupCounts());
    512 
    513   // id1 demoted to MAX->DEFAULT, no appearing as toast.
    514   priority.priority = DEFAULT_PRIORITY;
    515   notification.reset(new Notification(message_center::NOTIFICATION_TYPE_SIMPLE,
    516                                       id1,
    517                                       UTF8ToUTF16("newtitle3"),
    518                                       UTF8ToUTF16("newbody3"),
    519                                       gfx::Image(),
    520                                       UTF8ToUTF16(kDisplaySource),
    521                                       NotifierId(NotifierId::APPLICATION,
    522                                                  kExtensionId),
    523                                       priority,
    524                                       NULL));
    525   notification_list()->UpdateNotificationMessage(id1, notification.Pass());
    526   EXPECT_EQ(0u, GetPopupCounts());
    527 }
    528 
    529 TEST_F(NotificationListTest, NotificationOrderAndPriority) {
    530   base::Time now = base::Time::Now();
    531   message_center::RichNotificationData optional;
    532   optional.timestamp = now;
    533   optional.priority = 2;
    534   std::string max_id = AddNotification(optional);
    535 
    536   now += base::TimeDelta::FromSeconds(1);
    537   optional.timestamp = now;
    538   optional.priority = 1;
    539   std::string high_id = AddNotification(optional);
    540 
    541   now += base::TimeDelta::FromSeconds(1);
    542   optional.timestamp = now;
    543   optional.priority = 0;
    544   std::string default_id = AddNotification(optional);
    545 
    546   {
    547     // Popups: latest comes first.
    548     NotificationList::PopupNotifications popups = GetPopups();
    549     EXPECT_EQ(3u, popups.size());
    550     NotificationList::PopupNotifications::const_iterator iter = popups.begin();
    551     EXPECT_EQ(default_id, (*iter)->id());
    552     iter++;
    553     EXPECT_EQ(high_id, (*iter)->id());
    554     iter++;
    555     EXPECT_EQ(max_id, (*iter)->id());
    556   }
    557   {
    558     // Notifications: high priority comes ealier.
    559     const NotificationList::Notifications notifications =
    560         notification_list()->GetVisibleNotifications(blockers());
    561     EXPECT_EQ(3u, notifications.size());
    562     NotificationList::Notifications::const_iterator iter =
    563         notifications.begin();
    564     EXPECT_EQ(max_id, (*iter)->id());
    565     iter++;
    566     EXPECT_EQ(high_id, (*iter)->id());
    567     iter++;
    568     EXPECT_EQ(default_id, (*iter)->id());
    569   }
    570 }
    571 
    572 TEST_F(NotificationListTest, MarkSinglePopupAsShown) {
    573   std::string id1 = AddNotification();
    574   std::string id2 = AddNotification();
    575   std::string id3 = AddNotification();
    576   ASSERT_EQ(3u, notification_list()->NotificationCount(blockers()));
    577   ASSERT_EQ(std::min(static_cast<size_t>(3u), kMaxVisiblePopupNotifications),
    578             GetPopupCounts());
    579   notification_list()->MarkSinglePopupAsDisplayed(id1);
    580   notification_list()->MarkSinglePopupAsDisplayed(id2);
    581   notification_list()->MarkSinglePopupAsDisplayed(id3);
    582 
    583   notification_list()->MarkSinglePopupAsShown(id2, true);
    584   notification_list()->MarkSinglePopupAsShown(id3, false);
    585   EXPECT_EQ(3u, notification_list()->NotificationCount(blockers()));
    586   EXPECT_EQ(1u, notification_list()->UnreadCount(blockers()));
    587   EXPECT_EQ(1u, GetPopupCounts());
    588   NotificationList::PopupNotifications popups = GetPopups();
    589   EXPECT_EQ(id1, (*popups.begin())->id());
    590 
    591   // The notifications in the NotificationCenter are unaffected by popups shown.
    592   NotificationList::Notifications notifications =
    593       notification_list()->GetVisibleNotifications(blockers());
    594   NotificationList::Notifications::const_iterator iter = notifications.begin();
    595   EXPECT_EQ(id3, (*iter)->id());
    596   iter++;
    597   EXPECT_EQ(id2, (*iter)->id());
    598   iter++;
    599   EXPECT_EQ(id1, (*iter)->id());
    600 }
    601 
    602 TEST_F(NotificationListTest, UpdateAfterMarkedAsShown) {
    603   std::string id1 = AddNotification();
    604   std::string id2 = AddNotification();
    605   notification_list()->MarkSinglePopupAsDisplayed(id1);
    606   notification_list()->MarkSinglePopupAsDisplayed(id2);
    607 
    608   EXPECT_EQ(2u, GetPopupCounts());
    609 
    610   const Notification* n1 = GetNotification(id1);
    611   EXPECT_FALSE(n1->shown_as_popup());
    612   EXPECT_TRUE(n1->IsRead());
    613 
    614   notification_list()->MarkSinglePopupAsShown(id1, true);
    615 
    616   n1 = GetNotification(id1);
    617   EXPECT_TRUE(n1->shown_as_popup());
    618   EXPECT_TRUE(n1->IsRead());
    619 
    620   const std::string replaced("test-replaced-id");
    621   scoped_ptr<Notification> notification(
    622       new Notification(message_center::NOTIFICATION_TYPE_SIMPLE,
    623                        replaced,
    624                        UTF8ToUTF16("newtitle"),
    625                        UTF8ToUTF16("newbody"),
    626                        gfx::Image(),
    627                        UTF8ToUTF16(kDisplaySource),
    628                        NotifierId(NotifierId::APPLICATION, kExtensionId),
    629                        message_center::RichNotificationData(),
    630                        NULL));
    631   notification_list()->UpdateNotificationMessage(id1, notification.Pass());
    632   n1 = GetNotification(id1);
    633   EXPECT_TRUE(n1 == NULL);
    634   const Notification* nr = GetNotification(replaced);
    635   EXPECT_TRUE(nr->shown_as_popup());
    636   EXPECT_TRUE(nr->IsRead());
    637 }
    638 
    639 TEST_F(NotificationListTest, QuietMode) {
    640   notification_list()->SetQuietMode(true);
    641   AddNotification();
    642   AddPriorityNotification(HIGH_PRIORITY);
    643   AddPriorityNotification(MAX_PRIORITY);
    644   EXPECT_EQ(3u, notification_list()->NotificationCount(blockers()));
    645   EXPECT_EQ(0u, GetPopupCounts());
    646 
    647   notification_list()->SetQuietMode(false);
    648   AddNotification();
    649   EXPECT_EQ(4u, notification_list()->NotificationCount(blockers()));
    650   EXPECT_EQ(1u, GetPopupCounts());
    651 
    652   // TODO(mukai): Add test of quiet mode with expiration.
    653 }
    654 
    655 // Verifies that unread_count doesn't become negative.
    656 TEST_F(NotificationListTest, UnreadCountNoNegative) {
    657   std::string id = AddNotification();
    658   EXPECT_EQ(1u, notification_list()->UnreadCount(blockers()));
    659 
    660   notification_list()->MarkSinglePopupAsDisplayed(id);
    661   EXPECT_EQ(0u, notification_list()->UnreadCount(blockers()));
    662   notification_list()->MarkSinglePopupAsShown(
    663       id, false /* mark_notification_as_read */);
    664   EXPECT_EQ(1u, notification_list()->UnreadCount(blockers()));
    665 
    666   // Updates the notification  and verifies unread_count doesn't change.
    667   scoped_ptr<Notification> updated_notification(new Notification(
    668       message_center::NOTIFICATION_TYPE_SIMPLE,
    669       id,
    670       UTF8ToUTF16("updated"),
    671       UTF8ToUTF16("updated"),
    672       gfx::Image(),
    673       base::string16(),
    674       NotifierId(),
    675       RichNotificationData(),
    676       NULL));
    677   notification_list()->AddNotification(updated_notification.Pass());
    678   EXPECT_EQ(1u, notification_list()->UnreadCount(blockers()));
    679 }
    680 
    681 TEST_F(NotificationListTest, TestPushingShownNotification) {
    682   // Create a notification and mark it as shown.
    683   std::string id1;
    684   scoped_ptr<Notification> notification(MakeNotification(&id1));
    685   notification->set_shown_as_popup(true);
    686 
    687   // Call PushNotification on this notification.
    688   notification_list()->PushNotification(notification.Pass());
    689 
    690   // Ensure it is still marked as shown.
    691   EXPECT_TRUE(GetNotification(id1)->shown_as_popup());
    692 }
    693 
    694 TEST_F(NotificationListTest, TestHasNotificationOfType) {
    695   std::string id = AddNotification();
    696 
    697   EXPECT_TRUE(notification_list()->HasNotificationOfType(
    698       id, message_center::NOTIFICATION_TYPE_SIMPLE));
    699   EXPECT_FALSE(notification_list()->HasNotificationOfType(
    700       id, message_center::NOTIFICATION_TYPE_PROGRESS));
    701 
    702   scoped_ptr<Notification> updated_notification(new Notification(
    703       message_center::NOTIFICATION_TYPE_PROGRESS,
    704       id,
    705       UTF8ToUTF16("updated"),
    706       UTF8ToUTF16("updated"),
    707       gfx::Image(),
    708       base::string16(),
    709       NotifierId(),
    710       RichNotificationData(),
    711       NULL));
    712   notification_list()->AddNotification(updated_notification.Pass());
    713 
    714   EXPECT_FALSE(notification_list()->HasNotificationOfType(
    715       id, message_center::NOTIFICATION_TYPE_SIMPLE));
    716   EXPECT_TRUE(notification_list()->HasNotificationOfType(
    717       id, message_center::NOTIFICATION_TYPE_PROGRESS));
    718 }
    719 
    720 }  // namespace message_center
    721