Updating trunk VERSION from 2139.0 to 2140.0
[chromium-blink-merge.git] / ui / message_center / cocoa / notification_controller_unittest.mm
blob4a774414ceda17786f1a05f076f2331be8fcd63d
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.
5 #import "ui/message_center/cocoa/notification_controller.h"
7 #include "base/mac/foundation_util.h"
8 #include "base/mac/scoped_nsobject.h"
9 #include "base/memory/scoped_ptr.h"
10 #include "base/strings/sys_string_conversions.h"
11 #include "base/strings/utf_string_conversions.h"
12 #include "third_party/skia/include/core/SkBitmap.h"
13 #import "ui/base/cocoa/hover_image_button.h"
14 #import "ui/gfx/test/ui_cocoa_test_helper.h"
15 #include "ui/message_center/fake_message_center.h"
16 #include "ui/message_center/message_center_style.h"
17 #include "ui/message_center/notification.h"
18 #include "ui/message_center/notification_types.h"
20 using base::ASCIIToUTF16;
21 using base::UTF8ToUTF16;
23 namespace {
25 class MockMessageCenter : public message_center::FakeMessageCenter {
26  public:
27   MockMessageCenter()
28       : last_removed_by_user_(false),
29         remove_count_(0),
30         last_clicked_index_(-1) {}
32   virtual void RemoveNotification(const std::string& id,
33                                   bool by_user) OVERRIDE {
34     last_removed_id_ = id;
35     last_removed_by_user_ = by_user;
36     ++remove_count_;
37   }
39   virtual void ClickOnNotificationButton(const std::string& id,
40                                          int button_index) OVERRIDE {
41     last_clicked_id_ = id;
42     last_clicked_index_ = button_index;
43   }
45   const std::string& last_removed_id() const { return last_removed_id_; }
46   bool last_removed_by_user() const { return last_removed_by_user_; }
47   int remove_count() const { return remove_count_; }
48   const std::string& last_clicked_id() const { return last_clicked_id_; }
49   int last_clicked_index() const { return last_clicked_index_; }
51  private:
52   std::string last_removed_id_;
53   bool last_removed_by_user_;
54   int remove_count_;
56   std::string last_clicked_id_;
57   int last_clicked_index_;
59   DISALLOW_COPY_AND_ASSIGN(MockMessageCenter);
62 }  // namespace
64 @implementation MCNotificationController (TestingInterface)
65 - (NSButton*)closeButton {
66   return closeButton_.get();
69 - (NSImageView*)smallImageView {
70   return smallImage_.get();
73 - (NSButton*)secondButton {
74   // The buttons are in Cocoa-y-order, so the 2nd button is first.
75   NSView* view = [[bottomView_ subviews] objectAtIndex:0];
76   return base::mac::ObjCCastStrict<NSButton>(view);
79 - (NSArray*)bottomSubviews {
80   return [bottomView_ subviews];
83 - (NSImageView*)iconView {
84   return icon_.get();
87 - (NSTextView*)titleView {
88   return title_.get();
91 - (NSTextView*)messageView {
92   return message_.get();
95 - (NSTextView*)contextMessageView {
96   return contextMessage_.get();
99 - (NSView*)listView {
100   return listView_.get();
102 @end
104 namespace message_center {
106 class NotificationControllerTest : public ui::CocoaTest {
107  public:
108   NSImage* TestIcon() {
109     return [NSImage imageNamed:NSImageNameUser];
110   }
112  protected:
113   message_center::NotifierId DummyNotifierId() {
114     return message_center::NotifierId();
115   }
118 TEST_F(NotificationControllerTest, BasicLayout) {
119   scoped_ptr<message_center::Notification> notification(
120       new message_center::Notification(
121           message_center::NOTIFICATION_TYPE_SIMPLE,
122           "",
123           ASCIIToUTF16("Added to circles"),
124           ASCIIToUTF16("Jonathan and 5 others"),
125           gfx::Image(),
126           base::string16(),
127           DummyNotifierId(),
128           message_center::RichNotificationData(),
129           NULL));
130   gfx::Image testIcon([TestIcon() retain]);
131   notification->set_icon(testIcon);
132   notification->set_small_image(testIcon);
134   base::scoped_nsobject<MCNotificationController> controller(
135       [[MCNotificationController alloc] initWithNotification:notification.get()
136                                                messageCenter:NULL]);
137   [controller view];
139   EXPECT_EQ(TestIcon(), [[controller iconView] image]);
140   EXPECT_EQ(TestIcon(), [[controller smallImageView] image]);
141   EXPECT_EQ(base::SysNSStringToUTF16([[controller titleView] string]),
142             notification->title());
143   EXPECT_EQ(base::SysNSStringToUTF16([[controller messageView] string]),
144             notification->message());
145   EXPECT_EQ(controller.get(), [[controller closeButton] target]);
148 TEST_F(NotificationControllerTest, OverflowText) {
149   scoped_ptr<message_center::Notification> notification(
150       new message_center::Notification(
151           message_center::NOTIFICATION_TYPE_SIMPLE,
152           "",
153           ASCIIToUTF16("This is a much longer title that should wrap "
154                        "multiple lines."),
155           ASCIIToUTF16("And even the message is long. This sure is a wordy "
156                        "notification. Are you really going to read this "
157                        "entire thing?"),
158           gfx::Image(),
159           base::string16(),
160           DummyNotifierId(),
161           message_center::RichNotificationData(),
162           NULL));
163   base::scoped_nsobject<MCNotificationController> controller(
164       [[MCNotificationController alloc] initWithNotification:notification.get()
165                                                messageCenter:NULL]);
166   [controller view];
168   EXPECT_GT(NSHeight([[controller view] frame]),
169             message_center::kNotificationIconSize);
172 TEST_F(NotificationControllerTest, Close) {
173   scoped_ptr<message_center::Notification> notification(
174       new message_center::Notification(
175           message_center::NOTIFICATION_TYPE_SIMPLE,
176           "an_id",
177           base::string16(),
178           base::string16(),
179           gfx::Image(),
180           base::string16(),
181           DummyNotifierId(),
182           message_center::RichNotificationData(),
183           NULL));
184   MockMessageCenter message_center;
186   base::scoped_nsobject<MCNotificationController> controller(
187       [[MCNotificationController alloc] initWithNotification:notification.get()
188                                                messageCenter:&message_center]);
189   [controller view];
191   [[controller closeButton] performClick:nil];
193   EXPECT_EQ(1, message_center.remove_count());
194   EXPECT_EQ("an_id", message_center.last_removed_id());
195   EXPECT_TRUE(message_center.last_removed_by_user());
198 TEST_F(NotificationControllerTest, Update) {
199   scoped_ptr<message_center::Notification> notification(
200       new message_center::Notification(
201           message_center::NOTIFICATION_TYPE_SIMPLE,
202           "",
203           ASCIIToUTF16("A simple title"),
204           ASCIIToUTF16("This message isn't too long and should fit in the"
205                        "default bounds."),
206           gfx::Image(),
207           base::string16(),
208           DummyNotifierId(),
209           message_center::RichNotificationData(),
210           NULL));
211   base::scoped_nsobject<MCNotificationController> controller(
212       [[MCNotificationController alloc] initWithNotification:notification.get()
213                                                messageCenter:NULL]);
215   // Set up the default layout.
216   [controller view];
217   EXPECT_EQ(NSHeight([[controller view] frame]),
218             message_center::kNotificationIconSize);
219   EXPECT_FALSE([[controller iconView] image]);
220   EXPECT_FALSE([[controller smallImageView] image]);
222   // Update the icon.
223   gfx::Image testIcon([TestIcon() retain]);
224   notification->set_icon(testIcon);
225   notification->set_small_image(testIcon);
226   [controller updateNotification:notification.get()];
227   EXPECT_EQ(TestIcon(), [[controller iconView] image]);
228   EXPECT_EQ(TestIcon(), [[controller smallImageView] image]);
229   EXPECT_EQ(NSHeight([[controller view] frame]),
230             message_center::kNotificationIconSize);
233 TEST_F(NotificationControllerTest, Buttons) {
234   message_center::RichNotificationData optional;
235   message_center::ButtonInfo button1(UTF8ToUTF16("button1"));
236   optional.buttons.push_back(button1);
237   message_center::ButtonInfo button2(UTF8ToUTF16("button2"));
238   optional.buttons.push_back(button2);
240   scoped_ptr<message_center::Notification> notification(
241       new message_center::Notification(
242           message_center::NOTIFICATION_TYPE_BASE_FORMAT,
243           "an_id",
244           base::string16(),
245           base::string16(),
246           gfx::Image(),
247           base::string16(),
248           DummyNotifierId(),
249           optional,
250           NULL));
251   MockMessageCenter message_center;
253   base::scoped_nsobject<MCNotificationController> controller(
254       [[MCNotificationController alloc] initWithNotification:notification.get()
255                                                messageCenter:&message_center]);
256   [controller view];
258   [[controller secondButton] performClick:nil];
260   EXPECT_EQ("an_id", message_center.last_clicked_id());
261   EXPECT_EQ(1, message_center.last_clicked_index());
264 TEST_F(NotificationControllerTest, Image) {
265   scoped_ptr<message_center::Notification> notification(
266       new message_center::Notification(
267           message_center::NOTIFICATION_TYPE_BASE_FORMAT,
268           "an_id",
269           base::string16(),
270           base::string16(),
271           gfx::Image(),
272           base::string16(),
273           DummyNotifierId(),
274           message_center::RichNotificationData(),
275           NULL));
276   NSImage* image = [NSImage imageNamed:NSImageNameFolder];
277   notification->set_image(gfx::Image([image retain]));
279   MockMessageCenter message_center;
281   base::scoped_nsobject<MCNotificationController> controller(
282       [[MCNotificationController alloc] initWithNotification:notification.get()
283                                                messageCenter:&message_center]);
284   [controller view];
286   ASSERT_EQ(1u, [[controller bottomSubviews] count]);
287   ASSERT_TRUE([[[[controller bottomSubviews] lastObject] contentView]
288       isKindOfClass:[NSImageView class]]);
289   EXPECT_EQ(image,
290       [[[[controller bottomSubviews] lastObject] contentView] image]);
293 TEST_F(NotificationControllerTest, List) {
294   message_center::RichNotificationData optional;
295   message_center::NotificationItem item1(
296       UTF8ToUTF16("First title"), UTF8ToUTF16("first message"));
297   optional.items.push_back(item1);
298   message_center::NotificationItem item2(
299       UTF8ToUTF16("Second title"),
300       UTF8ToUTF16("second slightly longer message"));
301   optional.items.push_back(item2);
302   message_center::NotificationItem item3(
303       UTF8ToUTF16(""),    // Test for empty string.
304       UTF8ToUTF16(" "));  // Test for string containing only spaces.
305   optional.items.push_back(item3);
306   optional.context_message = UTF8ToUTF16("Context Message");
308   scoped_ptr<message_center::Notification> notification(
309       new message_center::Notification(
310           message_center::NOTIFICATION_TYPE_BASE_FORMAT,
311           "an_id",
312           UTF8ToUTF16("Notification Title"),
313           UTF8ToUTF16("Notification Message - should be hidden"),
314           gfx::Image(),
315           base::string16(),
316           DummyNotifierId(),
317           optional,
318           NULL));
320   MockMessageCenter message_center;
321   base::scoped_nsobject<MCNotificationController> controller(
322       [[MCNotificationController alloc] initWithNotification:notification.get()
323                                                messageCenter:&message_center]);
324   [controller view];
326   EXPECT_FALSE([[controller titleView] isHidden]);
327   EXPECT_TRUE([[controller messageView] isHidden]);
328   EXPECT_FALSE([[controller contextMessageView] isHidden]);
330   EXPECT_EQ(3u, [[[controller listView] subviews] count]);
331   EXPECT_LT(NSMaxY([[controller listView] frame]),
332             NSMinY([[controller titleView] frame]));
335 TEST_F(NotificationControllerTest, NoMessage) {
336   message_center::RichNotificationData optional;
337   optional.context_message = UTF8ToUTF16("Context Message");
339   scoped_ptr<message_center::Notification> notification(
340       new message_center::Notification(
341           message_center::NOTIFICATION_TYPE_BASE_FORMAT,
342           "an_id",
343           UTF8ToUTF16("Notification Title"),
344           UTF8ToUTF16(""),
345           gfx::Image(),
346           base::string16(),
347           DummyNotifierId(),
348           optional,
349           NULL));
351   MockMessageCenter message_center;
352   base::scoped_nsobject<MCNotificationController> controller(
353       [[MCNotificationController alloc] initWithNotification:notification.get()
354                                                messageCenter:&message_center]);
355   [controller view];
357   EXPECT_FALSE([[controller titleView] isHidden]);
358   EXPECT_TRUE([[controller messageView] isHidden]);
359   EXPECT_FALSE([[controller contextMessageView] isHidden]);
362 TEST_F(NotificationControllerTest, MessageSize) {
363   message_center::RichNotificationData data;
364   std::string id("id");
365   NotifierId notifier_id(NotifierId::APPLICATION, "notifier");
366   scoped_ptr<Notification> notification(new Notification(
367       NOTIFICATION_TYPE_BASE_FORMAT,
368       id,
369       base::UTF8ToUTF16(""),
370       ASCIIToUTF16("And\neven\nthe\nmessage is long.\nThis sure is wordy"),
371       gfx::Image(),
372       base::string16() /* display_source */,
373       notifier_id,
374       data,
375       NULL /* delegate */));
377   base::scoped_nsobject<MCNotificationController> controller(
378       [[MCNotificationController alloc] initWithNotification:notification.get()
379                                                messageCenter:NULL]);
381   // Set up the default layout.
382   [controller view];
384   auto compute_message_lines = ^{
385       NSString* string = [[[controller messageView] textStorage] string];
386       unsigned numberOfLines, index, stringLength = [string length];
387       for (index = 0, numberOfLines = 0; index < stringLength; numberOfLines++)
388         index = NSMaxRange([string lineRangeForRange:NSMakeRange(index, 0)]);
390       return numberOfLines;
391   };
393   // Message and no title: 5 lines.
394   EXPECT_EQ(5u, compute_message_lines());
396   // Message and one line title: 5 lines.
397   notification->set_title(ASCIIToUTF16("one line"));
398   [controller updateNotification:notification.get()];
399   EXPECT_EQ(5u, compute_message_lines());
401   // Message and two line title: 3 lines.
402   notification->set_title(ASCIIToUTF16("two\nlines"));
403   [controller updateNotification:notification.get()];
404   EXPECT_EQ(3u, compute_message_lines());
406   // Message, image and no title: 2 lines.
407   SkBitmap bitmap;
408   bitmap.allocN32Pixels(2, 2);
409   bitmap.eraseColor(SK_ColorGREEN);
410   notification->set_title(ASCIIToUTF16(""));
411   notification->set_image(gfx::Image::CreateFrom1xBitmap(bitmap));
412   [controller updateNotification:notification.get()];
413   EXPECT_EQ(2u, compute_message_lines());
415   // Message, image and one line title: 2 lines.
416   notification->set_title(ASCIIToUTF16("one line"));
417   [controller updateNotification:notification.get()];
418   EXPECT_EQ(2u, compute_message_lines());
420   // Message, image and two line title: 1 lines.
421   notification->set_title(ASCIIToUTF16("two\nlines"));
422   [controller updateNotification:notification.get()];
423   EXPECT_EQ(1u, compute_message_lines());
425   // Same as above, but context message takes away from message lines.
426   notification->set_context_message(base::UTF8ToUTF16("foo"));
427   notification->set_title(ASCIIToUTF16(""));
428   [controller updateNotification:notification.get()];
429   EXPECT_EQ(1u, compute_message_lines());
431   notification->set_title(ASCIIToUTF16("one line"));
432   [controller updateNotification:notification.get()];
433   EXPECT_EQ(1u, compute_message_lines());
435   notification->set_title(ASCIIToUTF16("two\nlines"));
436   [controller updateNotification:notification.get()];
437   EXPECT_EQ(0u, compute_message_lines());
440 }  // namespace message_center