Home | History | Annotate | Download | only in sync_notifier
      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:
     37   SyncedNotificationTest()
     38       : ui_thread_(content::BrowserThread::UI, &message_loop_) {}
     39   virtual ~SyncedNotificationTest() {}
     40 
     41   // Methods from testing::Test.
     42 
     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 
     70   virtual void TearDown() OVERRIDE {
     71     notification_manager_.reset();
     72   }
     73 
     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 
     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 
    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 
    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 
    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 
    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 
    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.
    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 
    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 
    163 TEST_F(SyncedNotificationTest, GetCreationTimeTest) {
    164   uint64 found_time = notification1_->GetCreationTime();
    165   EXPECT_EQ(kFakeCreationTime, found_time);
    166 }
    167 
    168 TEST_F(SyncedNotificationTest, GetPriorityTest) {
    169   double found_priority = notification1_->GetPriority();
    170   EXPECT_EQ(static_cast<double>(kNotificationPriority), found_priority);
    171 }
    172 
    173 TEST_F(SyncedNotificationTest, GetButtonCountTest) {
    174   int found_button_count = notification1_->GetButtonCount();
    175   EXPECT_EQ(2, found_button_count);
    176 }
    177 
    178 TEST_F(SyncedNotificationTest, GetNotificationCountTest) {
    179   int found_notification_count = notification1_->GetNotificationCount();
    180   EXPECT_EQ(3, found_notification_count);
    181 }
    182 
    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 
    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 
    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
    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 
    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 
    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 
    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 
    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 
    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.
    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 
    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 
    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