| OLD | NEW |
| 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #import "ui/message_center/cocoa/popup_collection.h" | 5 #import "ui/message_center/cocoa/popup_collection.h" |
| 6 | 6 |
| 7 #include "base/memory/scoped_nsobject.h" | 7 #include "base/memory/scoped_nsobject.h" |
| 8 #include "base/memory/scoped_ptr.h" | 8 #include "base/memory/scoped_ptr.h" |
| 9 #include "base/message_loop.h" | 9 #include "base/message_loop.h" |
| 10 #include "base/run_loop.h" | 10 #include "base/run_loop.h" |
| (...skipping 29 matching lines...) Expand all Loading... |
| 40 virtual void TearDown() OVERRIDE { | 40 virtual void TearDown() OVERRIDE { |
| 41 collection_.reset(); // Close all popups. | 41 collection_.reset(); // Close all popups. |
| 42 ui::CocoaTest::TearDown(); | 42 ui::CocoaTest::TearDown(); |
| 43 } | 43 } |
| 44 | 44 |
| 45 virtual ~PopupCollectionTest() { | 45 virtual ~PopupCollectionTest() { |
| 46 message_center::MessageCenter::Shutdown(); | 46 message_center::MessageCenter::Shutdown(); |
| 47 } | 47 } |
| 48 | 48 |
| 49 void AddThreeNotifications() { | 49 void AddThreeNotifications() { |
| 50 center_->AddNotification(message_center::NOTIFICATION_TYPE_SIMPLE, | 50 scoped_ptr<message_center::Notification> notification; |
| 51 "1", | 51 notification.reset(new message_center::Notification( |
| 52 ASCIIToUTF16("One"), | 52 message_center::NOTIFICATION_TYPE_SIMPLE, |
| 53 ASCIIToUTF16("This is the first notification to" | 53 "1", |
| 54 " be displayed"), | 54 ASCIIToUTF16("One"), |
| 55 string16(), | 55 ASCIIToUTF16("This is the first notification to" |
| 56 std::string(), | 56 " be displayed"), |
| 57 NULL, | 57 gfx::Image(), |
| 58 NULL); | 58 string16(), |
| 59 center_->AddNotification(message_center::NOTIFICATION_TYPE_SIMPLE, | 59 std::string(), |
| 60 "2", | 60 NULL, |
| 61 ASCIIToUTF16("Two"), | 61 NULL)); |
| 62 ASCIIToUTF16("This is the second notification."), | 62 center_->AddNotification(notification.Pass()); |
| 63 string16(), | |
| 64 std::string(), | |
| 65 NULL, | |
| 66 NULL); | |
| 67 center_->AddNotification(message_center::NOTIFICATION_TYPE_SIMPLE, | |
| 68 "3", | |
| 69 ASCIIToUTF16("Three"), | |
| 70 ASCIIToUTF16("This is the third notification " | |
| 71 "that has a much longer body " | |
| 72 "than the other notifications. It " | |
| 73 "may not fit on the screen if we " | |
| 74 "set the screen size too small."), | |
| 75 string16(), | |
| 76 std::string(), | |
| 77 NULL, | |
| 78 NULL); | |
| 79 | 63 |
| 64 notification.reset(new message_center::Notification( |
| 65 message_center::NOTIFICATION_TYPE_SIMPLE, |
| 66 "2", |
| 67 ASCIIToUTF16("Two"), |
| 68 ASCIIToUTF16("This is the second notification."), |
| 69 gfx::Image(), |
| 70 string16(), |
| 71 std::string(), |
| 72 NULL, |
| 73 NULL)); |
| 74 center_->AddNotification(notification.Pass()); |
| 75 |
| 76 notification.reset(new message_center::Notification( |
| 77 message_center::NOTIFICATION_TYPE_SIMPLE, |
| 78 "3", |
| 79 ASCIIToUTF16("Three"), |
| 80 ASCIIToUTF16("This is the third notification " |
| 81 "that has a much longer body " |
| 82 "than the other notifications. It " |
| 83 "may not fit on the screen if we " |
| 84 "set the screen size too small."), |
| 85 gfx::Image(), |
| 86 string16(), |
| 87 std::string(), |
| 88 NULL, |
| 89 NULL)); |
| 90 center_->AddNotification(notification.Pass()); |
| 80 WaitForAnimationEnded(); | 91 WaitForAnimationEnded(); |
| 81 } | 92 } |
| 82 | 93 |
| 83 bool CheckSpacingBetween(MCPopupController* upper, MCPopupController* lower) { | 94 bool CheckSpacingBetween(MCPopupController* upper, MCPopupController* lower) { |
| 84 CGFloat minY = NSMinY([[upper window] frame]); | 95 CGFloat minY = NSMinY([[upper window] frame]); |
| 85 CGFloat maxY = NSMaxY([[lower window] frame]); | 96 CGFloat maxY = NSMaxY([[lower window] frame]); |
| 86 CGFloat delta = minY - maxY; | 97 CGFloat delta = minY - maxY; |
| 87 EXPECT_EQ(message_center::kMarginBetweenItems, delta); | 98 EXPECT_EQ(message_center::kMarginBetweenItems, delta); |
| 88 return delta == message_center::kMarginBetweenItems; | 99 return delta == message_center::kMarginBetweenItems; |
| 89 } | 100 } |
| (...skipping 27 matching lines...) Expand all Loading... |
| 117 EXPECT_EQ(2u, [[collection_ popups] count]); | 128 EXPECT_EQ(2u, [[collection_ popups] count]); |
| 118 } | 129 } |
| 119 | 130 |
| 120 TEST_F(PopupCollectionTest, AttemptFourOneOffscreen) { | 131 TEST_F(PopupCollectionTest, AttemptFourOneOffscreen) { |
| 121 [collection_ setScreenFrame:NSMakeRect(0, 0, 800, 300)]; | 132 [collection_ setScreenFrame:NSMakeRect(0, 0, 800, 300)]; |
| 122 | 133 |
| 123 EXPECT_EQ(0u, [[collection_ popups] count]); | 134 EXPECT_EQ(0u, [[collection_ popups] count]); |
| 124 AddThreeNotifications(); | 135 AddThreeNotifications(); |
| 125 EXPECT_EQ(2u, [[collection_ popups] count]); // "3" does not fit on screen. | 136 EXPECT_EQ(2u, [[collection_ popups] count]); // "3" does not fit on screen. |
| 126 | 137 |
| 127 center_->AddNotification(message_center::NOTIFICATION_TYPE_SIMPLE, | 138 scoped_ptr<message_center::Notification> notification; |
| 128 "4", | 139 |
| 129 ASCIIToUTF16("Four"), | 140 notification.reset(new message_center::Notification( |
| 130 ASCIIToUTF16("This is the fourth notification."), | 141 message_center::NOTIFICATION_TYPE_SIMPLE, |
| 131 string16(), | 142 "4", |
| 132 std::string(), | 143 ASCIIToUTF16("Four"), |
| 133 NULL, | 144 ASCIIToUTF16("This is the fourth notification."), |
| 134 NULL); | 145 gfx::Image(), |
| 146 string16(), |
| 147 std::string(), |
| 148 NULL, |
| 149 NULL)); |
| 150 center_->AddNotification(notification.Pass()); |
| 135 WaitForAnimationEnded(); | 151 WaitForAnimationEnded(); |
| 136 | 152 |
| 137 // Remove "1" and "3" should fit on screen. | 153 // Remove "1" and "3" should fit on screen. |
| 138 center_->RemoveNotification("1", true); | 154 center_->RemoveNotification("1", true); |
| 139 WaitForAnimationEnded(); | 155 WaitForAnimationEnded(); |
| 140 ASSERT_EQ(2u, [[collection_ popups] count]); | 156 ASSERT_EQ(2u, [[collection_ popups] count]); |
| 141 | 157 |
| 142 EXPECT_EQ("2", [[[collection_ popups] objectAtIndex:0] notificationID]); | 158 EXPECT_EQ("2", [[[collection_ popups] objectAtIndex:0] notificationID]); |
| 143 EXPECT_EQ("3", [[[collection_ popups] objectAtIndex:1] notificationID]); | 159 EXPECT_EQ("3", [[[collection_ popups] objectAtIndex:1] notificationID]); |
| 144 | 160 |
| (...skipping 18 matching lines...) Expand all Loading... |
| 163 | 179 |
| 164 EXPECT_TRUE(CheckSpacingBetween([popups objectAtIndex:0], | 180 EXPECT_TRUE(CheckSpacingBetween([popups objectAtIndex:0], |
| 165 [popups objectAtIndex:1])); | 181 [popups objectAtIndex:1])); |
| 166 EXPECT_TRUE(CheckSpacingBetween([popups objectAtIndex:1], | 182 EXPECT_TRUE(CheckSpacingBetween([popups objectAtIndex:1], |
| 167 [popups objectAtIndex:2])); | 183 [popups objectAtIndex:2])); |
| 168 | 184 |
| 169 // Set priority so that kMaxVisiblePopupNotifications does not hide it. | 185 // Set priority so that kMaxVisiblePopupNotifications does not hide it. |
| 170 scoped_ptr<base::DictionaryValue> optional(new base::DictionaryValue); | 186 scoped_ptr<base::DictionaryValue> optional(new base::DictionaryValue); |
| 171 optional->SetInteger(message_center::kPriorityKey, | 187 optional->SetInteger(message_center::kPriorityKey, |
| 172 message_center::HIGH_PRIORITY); | 188 message_center::HIGH_PRIORITY); |
| 173 center_->AddNotification(message_center::NOTIFICATION_TYPE_SIMPLE, | 189 scoped_ptr<message_center::Notification> notification; |
| 174 "4", | 190 notification.reset(new message_center::Notification( |
| 175 ASCIIToUTF16("Four"), | 191 message_center::NOTIFICATION_TYPE_SIMPLE, |
| 176 ASCIIToUTF16("This is the fourth notification."), | 192 "4", |
| 177 string16(), | 193 ASCIIToUTF16("Four"), |
| 178 std::string(), | 194 ASCIIToUTF16("This is the fourth notification."), |
| 179 optional.get(), | 195 gfx::Image(), |
| 180 NULL); | 196 string16(), |
| 197 std::string(), |
| 198 optional.get(), |
| 199 NULL)); |
| 200 center_->AddNotification(notification.Pass()); |
| 181 WaitForAnimationEnded(); | 201 WaitForAnimationEnded(); |
| 182 EXPECT_TRUE(CheckSpacingBetween([popups objectAtIndex:2], | 202 EXPECT_TRUE(CheckSpacingBetween([popups objectAtIndex:2], |
| 183 [popups objectAtIndex:3])); | 203 [popups objectAtIndex:3])); |
| 184 | 204 |
| 185 // Remove "2". | 205 // Remove "2". |
| 186 center_->RemoveNotification("2", true); | 206 center_->RemoveNotification("2", true); |
| 187 WaitForAnimationEnded(); | 207 WaitForAnimationEnded(); |
| 188 EXPECT_TRUE(CheckSpacingBetween([popups objectAtIndex:0], | 208 EXPECT_TRUE(CheckSpacingBetween([popups objectAtIndex:0], |
| 189 [popups objectAtIndex:1])); | 209 [popups objectAtIndex:1])); |
| 190 EXPECT_TRUE(CheckSpacingBetween([popups objectAtIndex:1], | 210 EXPECT_TRUE(CheckSpacingBetween([popups objectAtIndex:1], |
| 191 [popups objectAtIndex:2])); | 211 [popups objectAtIndex:2])); |
| 192 | 212 |
| 193 // Remove "1". | 213 // Remove "1". |
| 194 center_->RemoveNotification("2", true); | 214 center_->RemoveNotification("2", true); |
| 195 WaitForAnimationEnded(); | 215 WaitForAnimationEnded(); |
| 196 EXPECT_EQ(message_center::kMarginBetweenItems, | 216 EXPECT_EQ(message_center::kMarginBetweenItems, |
| 197 kScreenSize - NSMaxY([[[popups objectAtIndex:0] window] frame])); | 217 kScreenSize - NSMaxY([[[popups objectAtIndex:0] window] frame])); |
| 198 EXPECT_TRUE(CheckSpacingBetween([popups objectAtIndex:0], | 218 EXPECT_TRUE(CheckSpacingBetween([popups objectAtIndex:0], |
| 199 [popups objectAtIndex:1])); | 219 [popups objectAtIndex:1])); |
| 200 } | 220 } |
| 201 | 221 |
| 202 TEST_F(PopupCollectionTest, TinyScreen) { | 222 TEST_F(PopupCollectionTest, TinyScreen) { |
| 203 [collection_ setScreenFrame:NSMakeRect(0, 0, 800, 100)]; | 223 [collection_ setScreenFrame:NSMakeRect(0, 0, 800, 100)]; |
| 204 | 224 |
| 205 EXPECT_EQ(0u, [[collection_ popups] count]); | 225 EXPECT_EQ(0u, [[collection_ popups] count]); |
| 206 center_->AddNotification(message_center::NOTIFICATION_TYPE_SIMPLE, | 226 scoped_ptr<message_center::Notification> notification; |
| 207 "1", | 227 notification.reset(new message_center::Notification( |
| 208 ASCIIToUTF16("One"), | 228 message_center::NOTIFICATION_TYPE_SIMPLE, |
| 209 ASCIIToUTF16("This is the first notification to" | 229 "1", |
| 210 " be displayed"), | 230 ASCIIToUTF16("One"), |
| 211 string16(), | 231 ASCIIToUTF16("This is the first notification to" |
| 212 std::string(), | 232 " be displayed"), |
| 213 NULL, | 233 gfx::Image(), |
| 214 NULL); | 234 string16(), |
| 235 std::string(), |
| 236 NULL, |
| 237 NULL)); |
| 238 center_->AddNotification(notification.Pass()); |
| 215 WaitForAnimationEnded(); | 239 WaitForAnimationEnded(); |
| 216 EXPECT_EQ(1u, [[collection_ popups] count]); | 240 EXPECT_EQ(1u, [[collection_ popups] count]); |
| 217 | 241 |
| 218 // Now give the notification a longer message so that it no longer fits. | 242 // Now give the notification a longer message so that it no longer fits. |
| 219 center_->UpdateNotification("1", | 243 notification.reset(new message_center::Notification( |
| 220 "1", | 244 message_center::NOTIFICATION_TYPE_SIMPLE, |
| 221 ASCIIToUTF16("One"), | 245 "1", |
| 222 ASCIIToUTF16("This is now a very very very very " | 246 ASCIIToUTF16("One"), |
| 223 "very very very very very very very " | 247 ASCIIToUTF16("This is now a very very very very " |
| 224 "very very very very very very very " | 248 "very very very very very very very " |
| 225 "very very very very very very very " | 249 "very very very very very very very " |
| 226 "very very very very very very very " | 250 "very very very very very very very " |
| 227 "very very very very very very very " | 251 "very very very very very very very " |
| 228 "very very very very very very very " | 252 "very very very very very very very " |
| 229 "long notification."), | 253 "very very very very very very very " |
| 230 NULL, | 254 "long notification."), |
| 231 NULL); | 255 gfx::Image(), |
| 256 string16(), |
| 257 std::string(), |
| 258 NULL, |
| 259 NULL)); |
| 260 center_->UpdateNotification("1", notification.Pass()); |
| 232 WaitForAnimationEnded(); | 261 WaitForAnimationEnded(); |
| 233 EXPECT_EQ(0u, [[collection_ popups] count]); | 262 EXPECT_EQ(0u, [[collection_ popups] count]); |
| 234 } | 263 } |
| 235 | 264 |
| 236 TEST_F(PopupCollectionTest, UpdateIconAndBody) { | 265 TEST_F(PopupCollectionTest, UpdateIconAndBody) { |
| 237 AddThreeNotifications(); | 266 AddThreeNotifications(); |
| 238 NSArray* popups = [collection_ popups]; | 267 NSArray* popups = [collection_ popups]; |
| 239 | 268 |
| 240 EXPECT_EQ(3u, [popups count]); | 269 EXPECT_EQ(3u, [popups count]); |
| 241 | 270 |
| 242 // Update "2" icon. | 271 // Update "2" icon. |
| 243 MCNotificationController* controller = | 272 MCNotificationController* controller = |
| 244 [[popups objectAtIndex:1] notificationController]; | 273 [[popups objectAtIndex:1] notificationController]; |
| 245 EXPECT_FALSE([[controller iconView] image]); | 274 EXPECT_FALSE([[controller iconView] image]); |
| 246 center_->SetNotificationIcon("2", | 275 center_->SetNotificationIcon("2", |
| 247 gfx::Image([[NSImage imageNamed:NSImageNameUser] retain])); | 276 gfx::Image([[NSImage imageNamed:NSImageNameUser] retain])); |
| 248 WaitForAnimationEnded(); | 277 WaitForAnimationEnded(); |
| 249 EXPECT_TRUE([[controller iconView] image]); | 278 EXPECT_TRUE([[controller iconView] image]); |
| 250 | 279 |
| 251 EXPECT_EQ(3u, [popups count]); | 280 EXPECT_EQ(3u, [popups count]); |
| 252 EXPECT_TRUE(CheckSpacingBetween([popups objectAtIndex:0], | 281 EXPECT_TRUE(CheckSpacingBetween([popups objectAtIndex:0], |
| 253 [popups objectAtIndex:1])); | 282 [popups objectAtIndex:1])); |
| 254 EXPECT_TRUE(CheckSpacingBetween([popups objectAtIndex:1], | 283 EXPECT_TRUE(CheckSpacingBetween([popups objectAtIndex:1], |
| 255 [popups objectAtIndex:2])); | 284 [popups objectAtIndex:2])); |
| 256 | 285 |
| 257 // Replace "1". | 286 // Replace "1". |
| 258 controller = [[popups objectAtIndex:0] notificationController]; | 287 controller = [[popups objectAtIndex:0] notificationController]; |
| 259 NSRect old_frame = [[controller view] frame]; | 288 NSRect old_frame = [[controller view] frame]; |
| 260 center_->AddNotification(message_center::NOTIFICATION_TYPE_SIMPLE, | 289 scoped_ptr<message_center::Notification> notification; |
| 261 "1", | 290 notification.reset(new message_center::Notification( |
| 262 ASCIIToUTF16("One is going to get a much longer " | 291 message_center::NOTIFICATION_TYPE_SIMPLE, |
| 263 "title than it previously had."), | 292 "1", |
| 264 ASCIIToUTF16("This is the first notification to " | 293 ASCIIToUTF16("One is going to get a much longer " |
| 265 "be displayed, but it will also be " | 294 "title than it previously had."), |
| 266 "updated to have a significantly " | 295 ASCIIToUTF16("This is the first notification to " |
| 267 "longer body"), | 296 "be displayed, but it will also be " |
| 268 string16(), | 297 "updated to have a significantly " |
| 269 std::string(), | 298 "longer body"), |
| 270 NULL, | 299 gfx::Image(), |
| 271 NULL); | 300 string16(), |
| 301 std::string(), |
| 302 NULL, |
| 303 NULL)); |
| 304 center_->AddNotification(notification.Pass()); |
| 272 WaitForAnimationEnded(); | 305 WaitForAnimationEnded(); |
| 273 EXPECT_GT(NSHeight([[controller view] frame]), NSHeight(old_frame)); | 306 EXPECT_GT(NSHeight([[controller view] frame]), NSHeight(old_frame)); |
| 274 | 307 |
| 275 // Test updated spacing. | 308 // Test updated spacing. |
| 276 EXPECT_EQ(3u, [popups count]); | 309 EXPECT_EQ(3u, [popups count]); |
| 277 EXPECT_TRUE(CheckSpacingBetween([popups objectAtIndex:0], | 310 EXPECT_TRUE(CheckSpacingBetween([popups objectAtIndex:0], |
| 278 [popups objectAtIndex:1])); | 311 [popups objectAtIndex:1])); |
| 279 EXPECT_TRUE(CheckSpacingBetween([popups objectAtIndex:1], | 312 EXPECT_TRUE(CheckSpacingBetween([popups objectAtIndex:1], |
| 280 [popups objectAtIndex:2])); | 313 [popups objectAtIndex:2])); |
| 281 EXPECT_EQ("1", [[popups objectAtIndex:0] notificationID]); | 314 EXPECT_EQ("1", [[popups objectAtIndex:0] notificationID]); |
| 282 EXPECT_EQ("2", [[popups objectAtIndex:1] notificationID]); | 315 EXPECT_EQ("2", [[popups objectAtIndex:1] notificationID]); |
| 283 EXPECT_EQ("3", [[popups objectAtIndex:2] notificationID]); | 316 EXPECT_EQ("3", [[popups objectAtIndex:2] notificationID]); |
| 284 } | 317 } |
| 285 | 318 |
| 286 TEST_F(PopupCollectionTest, CloseCollectionBeforeNewPopupAnimationEnds) { | 319 TEST_F(PopupCollectionTest, CloseCollectionBeforeNewPopupAnimationEnds) { |
| 287 // Add a notification and don't wait for the animation to finish. | 320 // Add a notification and don't wait for the animation to finish. |
| 288 center_->AddNotification(message_center::NOTIFICATION_TYPE_SIMPLE, | 321 scoped_ptr<message_center::Notification> notification; |
| 289 "1", | 322 notification.reset(new message_center::Notification( |
| 290 ASCIIToUTF16("One"), | 323 message_center::NOTIFICATION_TYPE_SIMPLE, |
| 291 ASCIIToUTF16("This is the first notification to" | 324 "1", |
| 292 " be displayed"), | 325 ASCIIToUTF16("One"), |
| 293 string16(), | 326 ASCIIToUTF16("This is the first notification to" |
| 294 std::string(), | 327 " be displayed"), |
| 295 NULL, | 328 gfx::Image(), |
| 296 NULL); | 329 string16(), |
| 330 std::string(), |
| 331 NULL, |
| 332 NULL)); |
| 333 center_->AddNotification(notification.Pass()); |
| 297 | 334 |
| 298 // Release the popup collection before the animation ends. No crash should | 335 // Release the popup collection before the animation ends. No crash should |
| 299 // be expected. | 336 // be expected. |
| 300 collection_.reset(); | 337 collection_.reset(); |
| 301 } | 338 } |
| 302 | 339 |
| 303 TEST_F(PopupCollectionTest, CloseCollectionBeforeClosePopupAnimationEnds) { | 340 TEST_F(PopupCollectionTest, CloseCollectionBeforeClosePopupAnimationEnds) { |
| 304 AddThreeNotifications(); | 341 AddThreeNotifications(); |
| 305 | 342 |
| 306 // Remove a notification and don't wait for the animation to finish. | 343 // Remove a notification and don't wait for the animation to finish. |
| 307 center_->RemoveNotification("1", true); | 344 center_->RemoveNotification("1", true); |
| 308 | 345 |
| 309 // Release the popup collection before the animation ends. No crash should | 346 // Release the popup collection before the animation ends. No crash should |
| 310 // be expected. | 347 // be expected. |
| 311 collection_.reset(); | 348 collection_.reset(); |
| 312 } | 349 } |
| 313 | 350 |
| 314 TEST_F(PopupCollectionTest, CloseCollectionBeforeUpdatePopupAnimationEnds) { | 351 TEST_F(PopupCollectionTest, CloseCollectionBeforeUpdatePopupAnimationEnds) { |
| 315 AddThreeNotifications(); | 352 AddThreeNotifications(); |
| 316 | 353 |
| 317 // Update a notification and don't wait for the animation to finish. | 354 // Update a notification and don't wait for the animation to finish. |
| 318 center_->UpdateNotification("1", | 355 scoped_ptr<message_center::Notification> notification; |
| 319 "1", | 356 notification.reset(new message_center::Notification( |
| 320 ASCIIToUTF16("One"), | 357 message_center::NOTIFICATION_TYPE_SIMPLE, |
| 321 ASCIIToUTF16("New message."), | 358 "1", |
| 322 NULL, | 359 ASCIIToUTF16("One"), |
| 323 NULL); | 360 ASCIIToUTF16("New message."), |
| 361 gfx::Image(), |
| 362 string16(), |
| 363 std::string(), |
| 364 NULL, |
| 365 NULL)); |
| 366 center_->UpdateNotification("1", notification.Pass()); |
| 324 | 367 |
| 325 // Release the popup collection before the animation ends. No crash should | 368 // Release the popup collection before the animation ends. No crash should |
| 326 // be expected. | 369 // be expected. |
| 327 collection_.reset(); | 370 collection_.reset(); |
| 328 } | 371 } |
| OLD | NEW |