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 #import "ui/base/cocoa/hover_image_button.h"
13 #import "ui/base/test/ui_cocoa_test_helper.h"
14 #include "ui/message_center/fake_message_center.h"
15 #include "ui/message_center/message_center_style.h"
16 #include "ui/message_center/notification.h"
17 #include "ui/message_center/notification_types.h"
21 class MockMessageCenter : public message_center::FakeMessageCenter {
24 : last_removed_by_user_(false),
26 last_clicked_index_(-1) {}
28 virtual void RemoveNotification(const std::string& id,
29 bool by_user) OVERRIDE {
30 last_removed_id_ = id;
31 last_removed_by_user_ = by_user;
35 virtual void ClickOnNotificationButton(const std::string& id,
36 int button_index) OVERRIDE {
37 last_clicked_id_ = id;
38 last_clicked_index_ = button_index;
41 const std::string& last_removed_id() const { return last_removed_id_; }
42 bool last_removed_by_user() const { return last_removed_by_user_; }
43 int remove_count() const { return remove_count_; }
44 const std::string& last_clicked_id() const { return last_clicked_id_; }
45 int last_clicked_index() const { return last_clicked_index_; }
48 std::string last_removed_id_;
49 bool last_removed_by_user_;
52 std::string last_clicked_id_;
53 int last_clicked_index_;
55 DISALLOW_COPY_AND_ASSIGN(MockMessageCenter);
60 @implementation MCNotificationController (TestingInterface)
61 - (NSButton*)closeButton {
62 return closeButton_.get();
65 - (NSButton*)secondButton {
66 // The buttons are in Cocoa-y-order, so the 2nd button is first.
67 NSView* view = [[bottomView_ subviews] objectAtIndex:0];
68 return base::mac::ObjCCastStrict<NSButton>(view);
71 - (NSArray*)bottomSubviews {
72 return [bottomView_ subviews];
75 - (NSImageView*)iconView {
79 - (NSTextView*)titleView {
83 - (NSTextView*)messageView {
84 return message_.get();
87 - (NSTextView*)contextMessageView {
88 return contextMessage_.get();
92 return listView_.get();
96 class NotificationControllerTest : public ui::CocoaTest {
99 return [NSImage imageNamed:NSImageNameUser];
103 TEST_F(NotificationControllerTest, BasicLayout) {
104 scoped_ptr<message_center::Notification> notification(
105 new message_center::Notification(
106 message_center::NOTIFICATION_TYPE_SIMPLE,
108 ASCIIToUTF16("Added to circles"),
109 ASCIIToUTF16("Jonathan and 5 others"),
112 message_center::NotifierId(),
113 message_center::RichNotificationData(),
115 notification->set_icon(gfx::Image([TestIcon() retain]));
117 base::scoped_nsobject<MCNotificationController> controller(
118 [[MCNotificationController alloc] initWithNotification:notification.get()
119 messageCenter:NULL]);
122 EXPECT_EQ(TestIcon(), [[controller iconView] image]);
123 EXPECT_EQ(base::SysNSStringToUTF16([[controller titleView] string]),
124 notification->title());
125 EXPECT_EQ(base::SysNSStringToUTF16([[controller messageView] string]),
126 notification->message());
127 EXPECT_EQ(controller.get(), [[controller closeButton] target]);
130 TEST_F(NotificationControllerTest, OverflowText) {
131 scoped_ptr<message_center::Notification> notification(
132 new message_center::Notification(
133 message_center::NOTIFICATION_TYPE_SIMPLE,
135 ASCIIToUTF16("This is a much longer title that should wrap "
137 ASCIIToUTF16("And even the message is long. This sure is a wordy "
138 "notification. Are you really going to read this "
142 message_center::NotifierId(),
143 message_center::RichNotificationData(),
145 base::scoped_nsobject<MCNotificationController> controller(
146 [[MCNotificationController alloc] initWithNotification:notification.get()
147 messageCenter:NULL]);
150 EXPECT_GT(NSHeight([[controller view] frame]),
151 message_center::kNotificationIconSize);
154 TEST_F(NotificationControllerTest, Close) {
155 scoped_ptr<message_center::Notification> notification(
156 new message_center::Notification(
157 message_center::NOTIFICATION_TYPE_SIMPLE,
163 message_center::NotifierId(),
164 message_center::RichNotificationData(),
166 MockMessageCenter message_center;
168 base::scoped_nsobject<MCNotificationController> controller(
169 [[MCNotificationController alloc] initWithNotification:notification.get()
170 messageCenter:&message_center]);
173 [[controller closeButton] performClick:nil];
175 EXPECT_EQ(1, message_center.remove_count());
176 EXPECT_EQ("an_id", message_center.last_removed_id());
177 EXPECT_TRUE(message_center.last_removed_by_user());
180 TEST_F(NotificationControllerTest, Update) {
181 scoped_ptr<message_center::Notification> notification(
182 new message_center::Notification(
183 message_center::NOTIFICATION_TYPE_SIMPLE,
185 ASCIIToUTF16("A simple title"),
186 ASCIIToUTF16("This message isn't too long and should fit in the"
190 message_center::NotifierId(),
191 message_center::RichNotificationData(),
193 base::scoped_nsobject<MCNotificationController> controller(
194 [[MCNotificationController alloc] initWithNotification:notification.get()
195 messageCenter:NULL]);
197 // Set up the default layout.
199 EXPECT_EQ(NSHeight([[controller view] frame]),
200 message_center::kNotificationIconSize);
201 EXPECT_FALSE([[controller iconView] image]);
204 notification->set_icon(gfx::Image([TestIcon() retain]));
205 [controller updateNotification:notification.get()];
206 EXPECT_EQ(TestIcon(), [[controller iconView] image]);
207 EXPECT_EQ(NSHeight([[controller view] frame]),
208 message_center::kNotificationIconSize);
211 TEST_F(NotificationControllerTest, Buttons) {
212 message_center::RichNotificationData optional;
213 message_center::ButtonInfo button1(UTF8ToUTF16("button1"));
214 optional.buttons.push_back(button1);
215 message_center::ButtonInfo button2(UTF8ToUTF16("button2"));
216 optional.buttons.push_back(button2);
218 scoped_ptr<message_center::Notification> notification(
219 new message_center::Notification(
220 message_center::NOTIFICATION_TYPE_BASE_FORMAT,
226 message_center::NotifierId(),
229 MockMessageCenter message_center;
231 base::scoped_nsobject<MCNotificationController> controller(
232 [[MCNotificationController alloc] initWithNotification:notification.get()
233 messageCenter:&message_center]);
236 [[controller secondButton] performClick:nil];
238 EXPECT_EQ("an_id", message_center.last_clicked_id());
239 EXPECT_EQ(1, message_center.last_clicked_index());
242 TEST_F(NotificationControllerTest, Image) {
243 scoped_ptr<message_center::Notification> notification(
244 new message_center::Notification(
245 message_center::NOTIFICATION_TYPE_BASE_FORMAT,
251 message_center::NotifierId(),
252 message_center::RichNotificationData(),
254 NSImage* image = [NSImage imageNamed:NSImageNameFolder];
255 notification->set_image(gfx::Image([image retain]));
257 MockMessageCenter message_center;
259 base::scoped_nsobject<MCNotificationController> controller(
260 [[MCNotificationController alloc] initWithNotification:notification.get()
261 messageCenter:&message_center]);
264 ASSERT_EQ(1u, [[controller bottomSubviews] count]);
265 ASSERT_TRUE([[[controller bottomSubviews] lastObject]
266 isKindOfClass:[NSImageView class]]);
267 EXPECT_EQ(image, [[[controller bottomSubviews] lastObject] image]);
270 TEST_F(NotificationControllerTest, List) {
271 message_center::RichNotificationData optional;
272 message_center::NotificationItem item1(
273 UTF8ToUTF16("First title"), UTF8ToUTF16("first message"));
274 optional.items.push_back(item1);
275 message_center::NotificationItem item2(
276 UTF8ToUTF16("Second title"),
277 UTF8ToUTF16("second slightly longer message"));
278 optional.items.push_back(item2);
279 message_center::NotificationItem item3(
280 UTF8ToUTF16(""), // Test for empty string.
281 UTF8ToUTF16(" ")); // Test for string containing only spaces.
282 optional.items.push_back(item3);
283 optional.context_message = UTF8ToUTF16("Context Message");
285 scoped_ptr<message_center::Notification> notification(
286 new message_center::Notification(
287 message_center::NOTIFICATION_TYPE_BASE_FORMAT,
289 UTF8ToUTF16("Notification Title"),
290 UTF8ToUTF16("Notification Message - should be hidden"),
293 message_center::NotifierId(),
297 MockMessageCenter message_center;
298 base::scoped_nsobject<MCNotificationController> controller(
299 [[MCNotificationController alloc] initWithNotification:notification.get()
300 messageCenter:&message_center]);
303 EXPECT_FALSE([[controller titleView] isHidden]);
304 EXPECT_TRUE([[controller messageView] isHidden]);
305 EXPECT_FALSE([[controller contextMessageView] isHidden]);
307 EXPECT_EQ(3u, [[[controller listView] subviews] count]);
308 EXPECT_LT(NSMaxY([[controller listView] frame]),
309 NSMinY([[controller titleView] frame]));