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