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