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