- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / browser / notifications / sync_notifier / synced_notification_unittest.cc
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 <string>
6
7 #include "base/memory/scoped_ptr.h"
8 #include "base/message_loop/message_loop.h"
9 #include "base/strings/utf_string_conversions.h"
10 #include "chrome/browser/notifications/notification.h"
11 #include "chrome/browser/notifications/notification_test_util.h"
12 #include "chrome/browser/notifications/notification_ui_manager.h"
13 #include "chrome/browser/notifications/sync_notifier/sync_notifier_test_utils.h"
14 #include "chrome/browser/notifications/sync_notifier/synced_notification.h"
15 #include "chrome/browser/profiles/profile.h"
16 #include "content/public/browser/browser_thread.h"
17 #include "content/public/test/test_browser_thread.h"
18 #include "testing/gtest/include/gtest/gtest.h"
19 #include "third_party/skia/include/core/SkBitmap.h"
20 #include "ui/message_center/message_center_util.h"
21 #include "ui/message_center/notification_types.h"
22
23 using syncer::SyncData;
24 using notifier::SyncedNotification;
25 using sync_pb::EntitySpecifics;
26 using sync_pb::SyncedNotificationSpecifics;
27
28 namespace {
29 const int kNotificationPriority = static_cast<int>(
30     message_center::LOW_PRIORITY);
31
32 bool UseRichNotifications() {
33   return message_center::IsRichNotificationEnabled();
34 }
35
36 }  // namespace
37
38 namespace notifier {
39
40 // Stub out the NotificationUIManager for unit testing.
41 class StubNotificationUIManager : public NotificationUIManager {
42  public:
43   StubNotificationUIManager()
44       : notification_(GURL(),
45                       GURL(),
46                       string16(),
47                       string16(),
48                       new MockNotificationDelegate("stub")) {}
49   virtual ~StubNotificationUIManager() {}
50
51   // Adds a notification to be displayed. Virtual for unit test override.
52   virtual void Add(const Notification& notification, Profile* profile)
53       OVERRIDE {
54     // Make a deep copy of the notification that we can inspect.
55     notification_ = notification;
56     profile_ = profile;
57   }
58
59   virtual bool Update(const Notification& notification, Profile* profile)
60       OVERRIDE {
61     // Make a deep copy of the notification that we can inspect.
62     notification_ = notification;
63     profile_ = profile;
64     return true;
65   }
66
67   // Returns true if any notifications match the supplied ID, either currently
68   // displayed or in the queue.
69   virtual const Notification* FindById(const std::string& id) const OVERRIDE {
70     return (notification_.id() == id) ? &notification_ : NULL;
71   }
72
73   // Removes any notifications matching the supplied ID, either currently
74   // displayed or in the queue.  Returns true if anything was removed.
75   virtual bool CancelById(const std::string& notification_id) OVERRIDE {
76     dismissed_id_ = notification_id;
77     return true;
78   }
79
80   virtual std::set<std::string> GetAllIdsByProfileAndSourceOrigin(
81       Profile* profile,
82       const GURL& source) OVERRIDE {
83     std::set<std::string> notification_ids;
84     if (source == notification_.origin_url() &&
85         profile->IsSameProfile(profile_))
86       notification_ids.insert(notification_.notification_id());
87     return notification_ids;
88   }
89
90   // Removes notifications matching the |source_origin| (which could be an
91   // extension ID). Returns true if anything was removed.
92   virtual bool CancelAllBySourceOrigin(const GURL& source_origin) OVERRIDE {
93     return false;
94   }
95
96   // Removes notifications matching |profile|. Returns true if any were removed.
97   virtual bool CancelAllByProfile(Profile* profile) OVERRIDE {
98     return false;
99   }
100
101   // Cancels all pending notifications and closes anything currently showing.
102   // Used when the app is terminating.
103   virtual void CancelAll() OVERRIDE {}
104
105   // Test hook to get the notification so we can check it
106   const Notification& notification() const { return notification_; }
107
108   // Test hook to check the ID of the last notification cancelled.
109   std::string& dismissed_id() { return dismissed_id_; }
110
111  private:
112   DISALLOW_COPY_AND_ASSIGN(StubNotificationUIManager);
113   Notification notification_;
114   Profile* profile_;
115   std::string dismissed_id_;
116 };
117
118 class SyncedNotificationTest : public testing::Test {
119  public:
120   SyncedNotificationTest()
121       : ui_thread_(content::BrowserThread::UI, &message_loop_) {}
122   virtual ~SyncedNotificationTest() {}
123
124   // Methods from testing::Test.
125
126   virtual void SetUp() OVERRIDE {
127     sync_data1_ = CreateSyncData(kTitle1, kText1, kIconUrl1, kImageUrl1,
128                                  kAppId1, kKey1, kUnread);
129     sync_data2_ = CreateSyncData(kTitle2, kText2, kIconUrl2, kImageUrl2,
130                                  kAppId2, kKey2, kUnread);
131     // Notification 3 will have the same ID as notification1, but different
132     // data inside.
133     sync_data3_ = CreateSyncData(kTitle3, kText3, kIconUrl3, kImageUrl3,
134                                  kAppId1, kKey1, kUnread);
135     // Notification 4 will be the same as 1, but the read state will be 'read'.
136     sync_data4_ = CreateSyncData(kTitle1, kText1, kIconUrl1, kImageUrl1,
137                                  kAppId1, kKey1, kDismissed);
138
139     notification1_.reset(new SyncedNotification(sync_data1_));
140     notification2_.reset(new SyncedNotification(sync_data2_));
141     notification3_.reset(new SyncedNotification(sync_data3_));
142     notification4_.reset(new SyncedNotification(sync_data4_));
143   }
144
145   virtual void TearDown() OVERRIDE {
146   }
147
148   virtual void AddButtonBitmaps(SyncedNotification* notification,
149                                 unsigned int how_many) {
150     for (unsigned int i = 0; i < how_many; ++i) {
151       notification->button_bitmaps_.push_back(gfx::Image());
152     }
153   }
154
155   scoped_ptr<SyncedNotification> notification1_;
156   scoped_ptr<SyncedNotification> notification2_;
157   scoped_ptr<SyncedNotification> notification3_;
158   scoped_ptr<SyncedNotification> notification4_;
159   syncer::SyncData sync_data1_;
160   syncer::SyncData sync_data2_;
161   syncer::SyncData sync_data3_;
162   syncer::SyncData sync_data4_;
163
164  private:
165   base::MessageLoopForIO message_loop_;
166   content::TestBrowserThread ui_thread_;
167
168   DISALLOW_COPY_AND_ASSIGN(SyncedNotificationTest);
169 };
170
171 // test simple accessors
172
173 TEST_F(SyncedNotificationTest, GetAppIdTest) {
174   std::string found_app_id = notification1_->GetAppId();
175   std::string expected_app_id(kAppId1);
176
177   EXPECT_EQ(found_app_id, expected_app_id);
178 }
179
180 TEST_F(SyncedNotificationTest, GetKeyTest) {
181   std::string found_key = notification1_->GetKey();
182   std::string expected_key(kKey1);
183
184   EXPECT_EQ(expected_key, found_key);
185 }
186
187 TEST_F(SyncedNotificationTest, GetTitleTest) {
188   std::string found_title = notification1_->GetTitle();
189   std::string expected_title(kTitle1);
190
191   EXPECT_EQ(expected_title, found_title);
192 }
193
194 TEST_F(SyncedNotificationTest, GetIconURLTest) {
195   std::string found_icon_url = notification1_->GetAppIconUrl().spec();
196   std::string expected_icon_url(kIconUrl1);
197
198   EXPECT_EQ(expected_icon_url, found_icon_url);
199 }
200
201 TEST_F(SyncedNotificationTest, GetReadStateTest) {
202   SyncedNotification::ReadState found_state1 =
203       notification1_->GetReadState();
204   SyncedNotification::ReadState expected_state1(SyncedNotification::kUnread);
205
206   EXPECT_EQ(expected_state1, found_state1);
207
208   SyncedNotification::ReadState found_state2 =
209       notification4_->GetReadState();
210   SyncedNotification::ReadState expected_state2(SyncedNotification::kDismissed);
211
212   EXPECT_EQ(expected_state2, found_state2);
213 }
214
215 // TODO(petewil): Improve ctor to pass in an image and type so this test can
216 // pass on actual data.
217 TEST_F(SyncedNotificationTest, GetImageURLTest) {
218   GURL found_image_url = notification1_->GetImageUrl();
219   GURL expected_image_url = GURL(kImageUrl1);
220
221   EXPECT_EQ(expected_image_url, found_image_url);
222 }
223
224 // TODO(petewil): test with a multi-line message
225 TEST_F(SyncedNotificationTest, GetTextTest) {
226   std::string found_text = notification1_->GetText();
227   std::string expected_text(kText1);
228
229   EXPECT_EQ(expected_text, found_text);
230 }
231
232 TEST_F(SyncedNotificationTest, GetCreationTimeTest) {
233   uint64 found_time = notification1_->GetCreationTime();
234   EXPECT_EQ(kFakeCreationTime, found_time);
235 }
236
237 TEST_F(SyncedNotificationTest, GetPriorityTest) {
238   double found_priority = notification1_->GetPriority();
239   EXPECT_EQ(static_cast<double>(kNotificationPriority), found_priority);
240 }
241
242 TEST_F(SyncedNotificationTest, GetButtonCountTest) {
243   int found_button_count = notification1_->GetButtonCount();
244   EXPECT_EQ(2, found_button_count);
245 }
246
247 TEST_F(SyncedNotificationTest, GetNotificationCountTest) {
248   int found_notification_count = notification1_->GetNotificationCount();
249   EXPECT_EQ(3, found_notification_count);
250 }
251
252 TEST_F(SyncedNotificationTest, GetDefaultDestinationDataTest) {
253     std::string default_destination_title =
254         notification1_->GetDefaultDestinationTitle();
255     GURL default_destination_icon_url =
256         notification1_->GetDefaultDestinationIconUrl();
257     GURL default_destination_url =
258         notification1_->GetDefaultDestinationUrl();
259     EXPECT_EQ(std::string(kDefaultDestinationTitle), default_destination_title);
260     EXPECT_EQ(GURL(kDefaultDestinationIconUrl),
261               default_destination_icon_url);
262     EXPECT_EQ(GURL(kDefaultDestinationUrl), default_destination_url);
263 }
264
265 TEST_F(SyncedNotificationTest, GetButtonDataTest) {
266     std::string button_one_title = notification1_->GetButtonTitle(0);
267     GURL button_one_icon_url = notification1_->GetButtonIconUrl(0);
268     GURL button_one_url = notification1_->GetButtonUrl(0);
269     std::string button_two_title = notification1_->GetButtonTitle(1);
270     GURL button_two_icon_url = notification1_->GetButtonIconUrl(1);
271     GURL button_two_url = notification1_->GetButtonUrl(1);
272     EXPECT_EQ(std::string(kButtonOneTitle), button_one_title);
273     EXPECT_EQ(GURL(kButtonOneIconUrl), button_one_icon_url);
274     EXPECT_EQ(GURL(kButtonOneUrl), button_one_url);
275     EXPECT_EQ(std::string(kButtonTwoTitle), button_two_title);
276     EXPECT_EQ(GURL(kButtonTwoIconUrl), button_two_icon_url);
277     EXPECT_EQ(GURL(kButtonTwoUrl), button_two_url);
278 }
279
280 TEST_F(SyncedNotificationTest, ContainedNotificationTest) {
281   std::string notification_title1 =
282       notification1_->GetContainedNotificationTitle(0);
283   std::string notification_title2 =
284       notification1_->GetContainedNotificationTitle(1);
285   std::string notification_title3 =
286       notification1_->GetContainedNotificationTitle(2);
287   std::string notification_message1 =
288       notification1_->GetContainedNotificationMessage(0);
289   std::string notification_message2 =
290       notification1_->GetContainedNotificationMessage(1);
291   std::string notification_message3 =
292       notification1_->GetContainedNotificationMessage(2);
293
294   EXPECT_EQ(std::string(kContainedTitle1), notification_title1);
295   EXPECT_EQ(std::string(kContainedTitle2), notification_title2);
296   EXPECT_EQ(std::string(kContainedTitle3), notification_title3);
297   EXPECT_EQ(std::string(kContainedMessage1), notification_message1);
298   EXPECT_EQ(std::string(kContainedMessage2), notification_message2);
299   EXPECT_EQ(std::string(kContainedMessage3), notification_message3);
300 }
301
302 // test that EqualsIgnoringReadState works as we expect
303 TEST_F(SyncedNotificationTest, EqualsIgnoringReadStateTest) {
304   EXPECT_TRUE(notification1_->EqualsIgnoringReadState(*notification1_));
305   EXPECT_TRUE(notification2_->EqualsIgnoringReadState(*notification2_));
306   EXPECT_FALSE(notification1_->EqualsIgnoringReadState(*notification2_));
307   EXPECT_FALSE(notification1_->EqualsIgnoringReadState(*notification3_));
308   EXPECT_TRUE(notification1_->EqualsIgnoringReadState(*notification4_));
309 }
310
311 TEST_F(SyncedNotificationTest, UpdateTest) {
312   scoped_ptr<SyncedNotification> notification5;
313   notification5.reset(new SyncedNotification(sync_data1_));
314
315   // update with the sync data from notification2, and ensure they are equal.
316   notification5->Update(sync_data2_);
317   EXPECT_TRUE(notification5->EqualsIgnoringReadState(*notification2_));
318   EXPECT_EQ(notification5->GetReadState(), notification2_->GetReadState());
319   EXPECT_FALSE(notification5->EqualsIgnoringReadState(*notification1_));
320 }
321
322 TEST_F(SyncedNotificationTest, ShowTest) {
323
324   if (!UseRichNotifications())
325     return;
326
327   StubNotificationUIManager notification_manager;
328
329   // Call the method under test using the pre-populated data.
330   notification1_->Show(&notification_manager, NULL, NULL);
331
332   const Notification notification = notification_manager.notification();
333
334   // Check the base fields of the notification.
335   EXPECT_EQ(message_center::NOTIFICATION_TYPE_IMAGE, notification.type());
336   EXPECT_EQ(std::string(kTitle1), UTF16ToUTF8(notification.title()));
337   EXPECT_EQ(std::string(kText1), UTF16ToUTF8(notification.message()));
338   EXPECT_EQ(std::string(kExpectedOriginUrl), notification.origin_url().spec());
339   EXPECT_EQ(std::string(kKey1), UTF16ToUTF8(notification.replace_id()));
340
341   EXPECT_EQ(kFakeCreationTime, notification.timestamp().ToDoubleT());
342   EXPECT_EQ(kNotificationPriority, notification.priority());
343 }
344
345 TEST_F(SyncedNotificationTest, DismissTest) {
346
347   if (!UseRichNotifications())
348     return;
349
350   StubNotificationUIManager notification_manager;
351
352   // Call the method under test using a dismissed notification.
353   notification4_->Show(&notification_manager, NULL, NULL);
354
355   EXPECT_EQ(std::string(kKey1), notification_manager.dismissed_id());
356 }
357
358 TEST_F(SyncedNotificationTest, AddBitmapToFetchQueueTest) {
359   scoped_ptr<SyncedNotification> notification6;
360   notification6.reset(new SyncedNotification(sync_data1_));
361
362   // Add two bitmaps to the queue.
363   notification6->AddBitmapToFetchQueue(GURL(kIconUrl1));
364   notification6->AddBitmapToFetchQueue(GURL(kIconUrl2));
365
366   EXPECT_EQ(2, notification6->active_fetcher_count_);
367   EXPECT_EQ(GURL(kIconUrl1), notification6->fetchers_[0]->url());
368   EXPECT_EQ(GURL(kIconUrl2), notification6->fetchers_[1]->url());
369
370   notification6->AddBitmapToFetchQueue(GURL(kIconUrl2));
371   EXPECT_EQ(2, notification6->active_fetcher_count_);
372 }
373
374 TEST_F(SyncedNotificationTest, OnFetchCompleteTest) {
375   if (!UseRichNotifications())
376     return;
377
378   StubNotificationUIManager notification_manager;
379
380   // Set up the internal state that FetchBitmaps() would have set.
381   notification1_->notification_manager_ = &notification_manager;
382
383   // Add the bitmaps to the queue for us to match up.
384   notification1_->AddBitmapToFetchQueue(GURL(kIconUrl1));
385   notification1_->AddBitmapToFetchQueue(GURL(kImageUrl1));
386   notification1_->AddBitmapToFetchQueue(GURL(kButtonOneIconUrl));
387   notification1_->AddBitmapToFetchQueue(GURL(kButtonTwoIconUrl));
388
389   EXPECT_EQ(4, notification1_->active_fetcher_count_);
390
391   // Put some realistic looking bitmap data into the url_fetcher.
392   SkBitmap bitmap;
393
394   // Put a real bitmap into "bitmap".  2x2 bitmap of green 32 bit pixels.
395   bitmap.setConfig(SkBitmap::kARGB_8888_Config, 2, 2);
396   bitmap.allocPixels();
397   bitmap.eraseColor(SK_ColorGREEN);
398
399   // Allocate the button_bitmaps_ array as the calling function normally would.
400   AddButtonBitmaps(notification1_.get(), 2);
401
402   notification1_->OnFetchComplete(GURL(kIconUrl1), &bitmap);
403   EXPECT_EQ(3, notification1_->active_fetcher_count_);
404
405   // When we call OnFetchComplete on the last bitmap, show should be called.
406   notification1_->OnFetchComplete(GURL(kImageUrl1), &bitmap);
407   EXPECT_EQ(2, notification1_->active_fetcher_count_);
408
409   notification1_->OnFetchComplete(GURL(kButtonOneIconUrl), &bitmap);
410   EXPECT_EQ(1, notification1_->active_fetcher_count_);
411
412   notification1_->OnFetchComplete(GURL(kButtonTwoIconUrl), &bitmap);
413   EXPECT_EQ(0, notification1_->active_fetcher_count_);
414
415   // Since we check Show() thoroughly in its own test, we only check cursorily.
416   EXPECT_EQ(message_center::NOTIFICATION_TYPE_IMAGE,
417             notification_manager.notification().type());
418   EXPECT_EQ(std::string(kTitle1),
419             UTF16ToUTF8(notification_manager.notification().title()));
420   EXPECT_EQ(std::string(kText1),
421             UTF16ToUTF8(notification_manager.notification().message()));
422
423   // TODO(petewil): Check that the bitmap in the notification is what we expect.
424   // This fails today, the type info is different.
425   // EXPECT_TRUE(gfx::BitmapsAreEqual(
426   //     image, notification1_->GetAppIconBitmap()));
427 }
428
429 TEST_F(SyncedNotificationTest, QueueBitmapFetchJobsTest) {
430   if (!UseRichNotifications())
431     return;
432
433   StubNotificationUIManager notification_manager;
434
435   notification1_->QueueBitmapFetchJobs(&notification_manager, NULL, NULL);
436
437   // There should be 4 urls in the queue, icon, image, and two buttons.
438   EXPECT_EQ(4, notification1_->active_fetcher_count_);
439 }
440
441 // TODO(petewil): Add a test for a notification being read and or deleted.
442
443 }  // namespace notifier