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.
5 #include "ui/message_center/notification_list.h"
7 #include "base/basictypes.h"
8 #include "base/i18n/time_formatting.h"
9 #include "base/stringprintf.h"
10 #include "base/utf_string_conversions.h"
11 #include "base/values.h"
12 #include "testing/gtest/include/gtest/gtest.h"
13 #include "ui/message_center/notification_types.h"
15 namespace message_center
{
18 class MockNotificationListDelegate
: public NotificationList::Delegate
{
20 MockNotificationListDelegate() : send_remove_count_(0) {}
21 virtual ~MockNotificationListDelegate() {}
23 size_t GetSendRemoveCountAndReset() {
24 size_t result
= send_remove_count_
;
25 send_remove_count_
= 0;
30 // Overridden from NotificationList::Delegate:
31 virtual void SendRemoveNotification(const std::string
& id
,
32 bool by_user
) OVERRIDE
{
36 virtual void OnQuietModeChanged(bool quiet_mode
) OVERRIDE
{
39 size_t send_remove_count_
;
40 DISALLOW_COPY_AND_ASSIGN(MockNotificationListDelegate
);
43 class NotificationListTest
: public testing::Test
{
45 NotificationListTest() {}
46 virtual ~NotificationListTest() {}
48 virtual void SetUp() {
49 delegate_
.reset(new MockNotificationListDelegate
);
50 notification_list_
.reset(new NotificationList(delegate_
.get()));
55 // Currently NotificationListTest doesn't care about some fields like title or
56 // message, so put a simple template on it. Returns the id of the new
58 std::string
AddNotification(const base::DictionaryValue
* optional_fields
) {
59 std::string new_id
= base::StringPrintf(kIdFormat
, counter_
);
60 notification_list_
->AddNotification(
61 message_center::NOTIFICATION_TYPE_SIMPLE
, new_id
,
62 UTF8ToUTF16(base::StringPrintf(kTitleFormat
, counter_
)),
63 UTF8ToUTF16(base::StringPrintf(kMessageFormat
, counter_
)),
64 UTF8ToUTF16(kDisplaySource
), kExtensionId
,
70 // Utility methods of AddNotification.
71 std::string
AddPriorityNotification(int priority
) {
72 base::DictionaryValue optional
;
73 optional
.SetInteger(message_center::kPriorityKey
, priority
);
74 return AddNotification(&optional
);
76 void SetupTimestampKey(const base::Time
& time
,
77 base::DictionaryValue
* optional
) {
78 string16 time_formatted
= base::TimeFormatShortDateAndTime(time
);
79 optional
->SetString(message_center::kTimestampKey
, time_formatted
);
82 size_t GetPopupCounts() {
83 return notification_list()->GetPopupNotifications().size();
86 MockNotificationListDelegate
* delegate() { return delegate_
.get(); }
87 NotificationList
* notification_list() { return notification_list_
.get(); }
90 static const char kIdFormat
[];
91 static const char kTitleFormat
[];
92 static const char kMessageFormat
[];
93 static const char kDisplaySource
[];
94 static const char kExtensionId
[];
96 scoped_ptr
<MockNotificationListDelegate
> delegate_
;
97 scoped_ptr
<NotificationList
> notification_list_
;
100 DISALLOW_COPY_AND_ASSIGN(NotificationListTest
);
103 const char NotificationListTest::kIdFormat
[] = "id%ld";
104 const char NotificationListTest::kTitleFormat
[] = "id%ld";
105 const char NotificationListTest::kMessageFormat
[] = "message%ld";
106 const char NotificationListTest::kDisplaySource
[] = "source";
107 const char NotificationListTest::kExtensionId
[] = "ext";
111 TEST_F(NotificationListTest
, Basic
) {
112 ASSERT_EQ(0u, notification_list()->NotificationCount());
113 ASSERT_EQ(0u, notification_list()->unread_count());
115 std::string id0
= AddNotification(NULL
);
116 EXPECT_EQ(1u, notification_list()->NotificationCount());
117 std::string id1
= AddNotification(NULL
);
118 EXPECT_EQ(2u, notification_list()->NotificationCount());
119 EXPECT_EQ(2u, notification_list()->unread_count());
121 EXPECT_TRUE(notification_list()->HasPopupNotifications());
122 EXPECT_TRUE(notification_list()->HasNotification(id0
));
123 EXPECT_TRUE(notification_list()->HasNotification(id1
));
124 EXPECT_FALSE(notification_list()->HasNotification(id1
+ "foo"));
126 EXPECT_EQ(2u, GetPopupCounts());
128 notification_list()->MarkPopupsAsShown(0);
129 EXPECT_EQ(2u, notification_list()->NotificationCount());
130 EXPECT_EQ(0u, GetPopupCounts());
132 notification_list()->RemoveNotification(id0
);
133 EXPECT_EQ(1u, notification_list()->NotificationCount());
134 EXPECT_EQ(1u, notification_list()->unread_count());
136 AddNotification(NULL
);
137 EXPECT_EQ(2u, notification_list()->NotificationCount());
139 notification_list()->RemoveAllNotifications();
140 EXPECT_EQ(0u, notification_list()->NotificationCount());
141 EXPECT_EQ(0u, notification_list()->unread_count());
144 TEST_F(NotificationListTest
, MessageCenterVisible
) {
145 AddNotification(NULL
);
146 EXPECT_EQ(1u, notification_list()->NotificationCount());
147 ASSERT_EQ(1u, notification_list()->unread_count());
149 // Toggle the message center visibility. It resets the unread count when
151 notification_list()->SetMessageCenterVisible(true);
152 ASSERT_EQ(1u, notification_list()->unread_count());
153 notification_list()->SetMessageCenterVisible(false);
154 ASSERT_EQ(0u, notification_list()->unread_count());
157 TEST_F(NotificationListTest
, UpdateNotification
) {
158 std::string id0
= AddNotification(NULL
);
159 std::string replaced
= id0
+ "_replaced";
160 EXPECT_EQ(1u, notification_list()->NotificationCount());
161 notification_list()->UpdateNotificationMessage(
162 id0
, replaced
, UTF8ToUTF16("newtitle"), UTF8ToUTF16("newbody"), NULL
);
163 EXPECT_EQ(1u, notification_list()->NotificationCount());
164 const NotificationList::Notifications
& notifications
=
165 notification_list()->GetNotifications();
166 EXPECT_EQ(replaced
, (*notifications
.begin())->id());
167 EXPECT_EQ(UTF8ToUTF16("newtitle"), (*notifications
.begin())->title());
168 EXPECT_EQ(UTF8ToUTF16("newbody"), (*notifications
.begin())->message());
171 TEST_F(NotificationListTest
, SendRemoveNotifications
) {
172 notification_list()->AddNotification(
173 message_center::NOTIFICATION_TYPE_SIMPLE
, "id0", UTF8ToUTF16("title0"),
174 UTF8ToUTF16("message0"), UTF8ToUTF16("source0"), "ext0", NULL
);
175 notification_list()->AddNotification(
176 message_center::NOTIFICATION_TYPE_SIMPLE
, "id1", UTF8ToUTF16("title1"),
177 UTF8ToUTF16("message1"), UTF8ToUTF16("source0"), "ext0", NULL
);
178 notification_list()->AddNotification(
179 message_center::NOTIFICATION_TYPE_SIMPLE
, "id2", UTF8ToUTF16("title1"),
180 UTF8ToUTF16("message1"), UTF8ToUTF16("source1"), "ext0", NULL
);
181 notification_list()->AddNotification(
182 message_center::NOTIFICATION_TYPE_SIMPLE
, "id3", UTF8ToUTF16("title1"),
183 UTF8ToUTF16("message1"), UTF8ToUTF16("source2"), "ext1", NULL
);
185 notification_list()->SendRemoveNotificationsBySource("id0");
186 EXPECT_EQ(2u, delegate()->GetSendRemoveCountAndReset());
187 notification_list()->SendRemoveNotificationsByExtension("id0");
188 EXPECT_EQ(3u, delegate()->GetSendRemoveCountAndReset());
191 TEST_F(NotificationListTest
, OldPopupShouldNotBeHidden
) {
192 std::vector
<std::string
> ids
;
193 for (size_t i
= 0; i
<= NotificationList::kMaxVisiblePopupNotifications
;
195 ids
.push_back(AddNotification(NULL
));
198 NotificationList::PopupNotifications popups
=
199 notification_list()->GetPopupNotifications();
200 // The popup should contain the oldest kMaxVisiblePopupNotifications. Newer
201 // one should come earlier in the popup list. It means, the last element
202 // of |popups| should be the firstly added one, and so on.
203 EXPECT_EQ(NotificationList::kMaxVisiblePopupNotifications
, popups
.size());
204 NotificationList::PopupNotifications::const_reverse_iterator iter
=
206 for (size_t i
= 0; i
< NotificationList::kMaxVisiblePopupNotifications
;
208 EXPECT_EQ(ids
[i
], (*iter
)->id()) << i
;
211 notification_list()->MarkPopupsAsShown(message_center::DEFAULT_PRIORITY
);
213 popups
= notification_list()->GetPopupNotifications();
214 EXPECT_EQ(1u, popups
.size());
215 EXPECT_EQ(ids
[ids
.size() - 1], (*popups
.begin())->id());
218 TEST_F(NotificationListTest
, Priority
) {
219 ASSERT_EQ(0u, notification_list()->NotificationCount());
220 ASSERT_EQ(0u, notification_list()->unread_count());
222 // Default priority has the limit on the number of the popups.
223 for (size_t i
= 0; i
<= NotificationList::kMaxVisiblePopupNotifications
;
225 AddNotification(NULL
);
227 EXPECT_EQ(NotificationList::kMaxVisiblePopupNotifications
+ 1,
228 notification_list()->NotificationCount());
229 EXPECT_EQ(NotificationList::kMaxVisiblePopupNotifications
, GetPopupCounts());
231 // Low priority: not visible to popups.
232 notification_list()->SetMessageCenterVisible(true);
233 notification_list()->SetMessageCenterVisible(false);
234 EXPECT_EQ(0u, notification_list()->unread_count());
235 AddPriorityNotification(-1);
236 EXPECT_EQ(NotificationList::kMaxVisiblePopupNotifications
+ 2,
237 notification_list()->NotificationCount());
238 EXPECT_EQ(1u, notification_list()->unread_count());
239 EXPECT_EQ(0u, GetPopupCounts());
241 // Minimum priority: doesn't update the unread count.
242 AddPriorityNotification(-2);
243 EXPECT_EQ(NotificationList::kMaxVisiblePopupNotifications
+ 3,
244 notification_list()->NotificationCount());
245 EXPECT_EQ(1u, notification_list()->unread_count());
246 EXPECT_EQ(0u, GetPopupCounts());
248 notification_list()->RemoveAllNotifications();
250 // Higher priority: no limits to the number of popups.
251 for (size_t i
= 0; i
< NotificationList::kMaxVisiblePopupNotifications
* 2;
253 AddPriorityNotification(1);
255 for (size_t i
= 0; i
< NotificationList::kMaxVisiblePopupNotifications
* 2;
257 AddPriorityNotification(2);
259 EXPECT_EQ(NotificationList::kMaxVisiblePopupNotifications
* 4,
260 notification_list()->NotificationCount());
261 EXPECT_EQ(NotificationList::kMaxVisiblePopupNotifications
* 4,
265 TEST_F(NotificationListTest
, HasPopupsWithPriority
) {
266 ASSERT_EQ(0u, notification_list()->NotificationCount());
267 ASSERT_EQ(0u, notification_list()->unread_count());
269 AddPriorityNotification(-2);
270 AddPriorityNotification(2);
272 EXPECT_EQ(1u, GetPopupCounts());
275 TEST_F(NotificationListTest
, PriorityPromotion
) {
276 std::string id0
= AddPriorityNotification(-1);
277 std::string replaced
= id0
+ "_replaced";
278 EXPECT_EQ(1u, notification_list()->NotificationCount());
279 EXPECT_EQ(0u, GetPopupCounts());
280 base::DictionaryValue optional
;
281 optional
.SetInteger(message_center::kPriorityKey
, 1);
282 notification_list()->UpdateNotificationMessage(
283 id0
, replaced
, UTF8ToUTF16("newtitle"), UTF8ToUTF16("newbody"),
285 EXPECT_EQ(1u, notification_list()->NotificationCount());
286 EXPECT_EQ(1u, GetPopupCounts());
287 const NotificationList::Notifications
& notifications
=
288 notification_list()->GetNotifications();
289 EXPECT_EQ(replaced
, (*notifications
.begin())->id());
290 EXPECT_EQ(UTF8ToUTF16("newtitle"), (*notifications
.begin())->title());
291 EXPECT_EQ(UTF8ToUTF16("newbody"), (*notifications
.begin())->message());
292 EXPECT_EQ(1, (*notifications
.begin())->priority());
295 TEST_F(NotificationListTest
, NotificationOrderAndPriority
) {
296 base::Time now
= base::Time::Now();
297 base::DictionaryValue optional
;
298 SetupTimestampKey(now
, &optional
);
299 optional
.SetInteger(message_center::kPriorityKey
, 2);
300 std::string max_id
= AddNotification(&optional
);
301 now
+= base::TimeDelta::FromSeconds(1);
302 SetupTimestampKey(now
, &optional
);
303 optional
.SetInteger(message_center::kPriorityKey
, 1);
304 std::string high_id
= AddNotification(&optional
);
305 now
+= base::TimeDelta::FromSeconds(1);
306 SetupTimestampKey(now
, &optional
);
307 optional
.SetInteger(message_center::kPriorityKey
, 0);
308 std::string default_id
= AddNotification(&optional
);
311 // Popups: latest comes first.
312 NotificationList::PopupNotifications popups
=
313 notification_list()->GetPopupNotifications();
314 EXPECT_EQ(3u, popups
.size());
315 NotificationList::PopupNotifications::const_iterator iter
= popups
.begin();
316 EXPECT_EQ(default_id
, (*iter
)->id());
318 EXPECT_EQ(high_id
, (*iter
)->id());
320 EXPECT_EQ(max_id
, (*iter
)->id());
323 // Notifications: high priority comes ealier.
324 const NotificationList::Notifications
& notifications
=
325 notification_list()->GetNotifications();
326 EXPECT_EQ(3u, notifications
.size());
327 NotificationList::Notifications::const_iterator iter
=
328 notifications
.begin();
329 EXPECT_EQ(max_id
, (*iter
)->id());
331 EXPECT_EQ(high_id
, (*iter
)->id());
333 EXPECT_EQ(default_id
, (*iter
)->id());
337 TEST_F(NotificationListTest
, MarkSinglePopupAsShown
) {
338 std::string id1
= AddNotification(NULL
);
339 std::string id2
= AddNotification(NULL
);
340 std::string id3
= AddNotification(NULL
);
341 ASSERT_EQ(3u, notification_list()->NotificationCount());
342 ASSERT_EQ(std::min(static_cast<size_t>(3u),
343 NotificationList::kMaxVisiblePopupNotifications
),
346 notification_list()->MarkSinglePopupAsShown(id2
, true);
347 notification_list()->MarkSinglePopupAsShown(id3
, false);
348 EXPECT_EQ(3u, notification_list()->NotificationCount());
349 EXPECT_EQ(2u, notification_list()->unread_count());
350 EXPECT_EQ(1u, GetPopupCounts());
351 NotificationList::PopupNotifications popups
=
352 notification_list()->GetPopupNotifications();
353 EXPECT_EQ(id1
, (*popups
.begin())->id());
355 // The notifications in the NotificationCenter are unaffected by popups shown.
356 NotificationList::Notifications notifications
=
357 notification_list()->GetNotifications();
358 NotificationList::Notifications::const_iterator iter
= notifications
.begin();
359 EXPECT_EQ(id3
, (*iter
)->id());
361 EXPECT_EQ(id2
, (*iter
)->id());
363 EXPECT_EQ(id1
, (*iter
)->id());
365 // Trickier scenario.
366 notification_list()->MarkPopupsAsShown(message_center::DEFAULT_PRIORITY
);
367 std::string id4
= AddNotification(NULL
);
368 std::string id5
= AddNotification(NULL
);
369 std::string id6
= AddNotification(NULL
);
370 notification_list()->MarkSinglePopupAsShown(id5
, true);
374 popups
= notification_list()->GetPopupNotifications();
375 EXPECT_EQ(2u, popups
.size());
376 NotificationList::PopupNotifications::const_iterator iter
= popups
.begin();
377 EXPECT_EQ(id6
, (*iter
)->id());
379 EXPECT_EQ(id4
, (*iter
)->id());
382 notifications
.clear();
383 notifications
= notification_list()->GetNotifications();
384 EXPECT_EQ(6u, notifications
.size());
385 iter
= notifications
.begin();
386 EXPECT_EQ(id6
, (*iter
)->id());
388 EXPECT_EQ(id5
, (*iter
)->id());
390 EXPECT_EQ(id4
, (*iter
)->id());
392 EXPECT_EQ(id3
, (*iter
)->id());
394 EXPECT_EQ(id2
, (*iter
)->id());
396 EXPECT_EQ(id1
, (*iter
)->id());
399 TEST_F(NotificationListTest
, QuietMode
) {
400 notification_list()->SetQuietMode(true);
401 AddNotification(NULL
);
402 AddPriorityNotification(1);
403 AddPriorityNotification(2);
404 EXPECT_EQ(3u, notification_list()->NotificationCount());
405 EXPECT_EQ(0u, GetPopupCounts());
406 // TODO(mukai): fix here when notification_list distinguish dismiss by quiet
407 // mode and by user operation.
408 EXPECT_EQ(0u, notification_list()->unread_count());
410 notification_list()->SetQuietMode(false);
411 AddNotification(NULL
);
412 EXPECT_EQ(4u, notification_list()->NotificationCount());
413 EXPECT_EQ(1u, GetPopupCounts());
415 // TODO(mukai): Add test of quiet mode with expiration.
418 } // namespace message_center