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/tray_view_controller.h"
7 #include "base/mac/scoped_nsobject.h"
8 #include "base/message_loop/message_loop.h"
9 #include "base/run_loop.h"
10 #include "base/strings/utf_string_conversions.h"
11 #import "ui/gfx/test/ui_cocoa_test_helper.h"
12 #include "ui/message_center/fake_notifier_settings_provider.h"
13 #include "ui/message_center/message_center.h"
14 #include "ui/message_center/message_center_impl.h"
15 #include "ui/message_center/message_center_style.h"
16 #include "ui/message_center/notification.h"
17 #include "ui/message_center/notifier_settings.h"
19 using base::ASCIIToUTF16;
21 namespace message_center {
23 class TrayViewControllerTest : public ui::CocoaTest {
25 TrayViewControllerTest()
29 void SetUp() override {
30 ui::CocoaTest::SetUp();
31 message_center::MessageCenter::Initialize();
32 center_ = message_center::MessageCenter::Get();
33 center_->DisableTimersForTest();
34 tray_.reset([[MCTrayViewController alloc] initWithMessageCenter:center_]);
35 [tray_ setAnimationDuration:0.002];
36 [tray_ setAnimateClearingNextNotificationDelay:0.001];
37 [tray_ setAnimationEndedCallback:^{
38 if (nested_run_loop_.get())
39 nested_run_loop_->Quit();
41 [tray_ view]; // Create the view.
44 void TearDown() override {
46 message_center::MessageCenter::Shutdown();
47 ui::CocoaTest::TearDown();
50 void WaitForAnimationEnded() {
51 if (![tray_ isAnimating])
53 nested_run_loop_.reset(new base::RunLoop());
54 nested_run_loop_->Run();
55 nested_run_loop_.reset();
59 message_center::NotifierId DummyNotifierId() {
60 return message_center::NotifierId();
63 message_center::MessageCenter* center_; // Weak, global.
65 base::MessageLoopForUI message_loop_;
66 scoped_ptr<base::RunLoop> nested_run_loop_;
67 base::scoped_nsobject<MCTrayViewController> tray_;
70 TEST_F(TrayViewControllerTest, AddRemoveOne) {
71 NSScrollView* view = [[tray_ scrollView] documentView];
72 EXPECT_EQ(0u, [[view subviews] count]);
73 scoped_ptr<message_center::Notification> notification_data;
74 notification_data.reset(new message_center::Notification(
75 message_center::NOTIFICATION_TYPE_SIMPLE,
77 ASCIIToUTF16("First notification"),
78 ASCIIToUTF16("This is a simple test."),
82 message_center::RichNotificationData(),
84 center_->AddNotification(notification_data.Pass());
85 [tray_ onMessageCenterTrayChanged];
86 ASSERT_EQ(1u, [[view subviews] count]);
88 // The view should have padding around it.
89 NSView* notification = [[view subviews] objectAtIndex:0];
90 NSRect notification_frame = [notification frame];
91 EXPECT_CGFLOAT_EQ(2 * message_center::kMarginBetweenItems,
92 NSHeight([view frame]) - NSHeight(notification_frame));
93 EXPECT_CGFLOAT_EQ(2 * message_center::kMarginBetweenItems,
94 NSWidth([view frame]) - NSWidth(notification_frame));
95 EXPECT_GT(NSHeight([[tray_ view] frame]),
96 NSHeight([[tray_ scrollView] frame]));
98 center_->RemoveNotification("1", true);
99 [tray_ onMessageCenterTrayChanged];
100 EXPECT_EQ(0u, [[view subviews] count]);
101 // The empty tray is now 100px tall to accommodate
102 // the empty message.
103 EXPECT_CGFLOAT_EQ(message_center::kMinScrollViewHeight,
104 NSHeight([view frame]));
107 TEST_F(TrayViewControllerTest, AddThreeClearAll) {
108 NSScrollView* view = [[tray_ scrollView] documentView];
109 EXPECT_EQ(0u, [[view subviews] count]);
110 scoped_ptr<message_center::Notification> notification;
111 notification.reset(new message_center::Notification(
112 message_center::NOTIFICATION_TYPE_SIMPLE,
114 ASCIIToUTF16("First notification"),
115 ASCIIToUTF16("This is a simple test."),
119 message_center::RichNotificationData(),
121 center_->AddNotification(notification.Pass());
122 notification.reset(new message_center::Notification(
123 message_center::NOTIFICATION_TYPE_SIMPLE,
125 ASCIIToUTF16("Second notification"),
126 ASCIIToUTF16("This is a simple test."),
130 message_center::RichNotificationData(),
132 center_->AddNotification(notification.Pass());
133 notification.reset(new message_center::Notification(
134 message_center::NOTIFICATION_TYPE_SIMPLE,
136 ASCIIToUTF16("Third notification"),
137 ASCIIToUTF16("This is a simple test."),
141 message_center::RichNotificationData(),
143 center_->AddNotification(notification.Pass());
144 [tray_ onMessageCenterTrayChanged];
145 ASSERT_EQ(3u, [[view subviews] count]);
147 [tray_ clearAllNotifications:nil];
148 WaitForAnimationEnded();
149 [tray_ onMessageCenterTrayChanged];
151 EXPECT_EQ(0u, [[view subviews] count]);
152 // The empty tray is now 100px tall to accommodate
153 // the empty message.
154 EXPECT_CGFLOAT_EQ(message_center::kMinScrollViewHeight,
155 NSHeight([view frame]));
158 TEST_F(TrayViewControllerTest, NoClearAllWhenNoNotifications) {
159 EXPECT_TRUE([tray_ pauseButton]);
160 EXPECT_TRUE([tray_ clearAllButton]);
162 // With no notifications, the clear all button should be hidden.
163 EXPECT_TRUE([[tray_ clearAllButton] isHidden]);
164 EXPECT_LT(NSMinX([[tray_ clearAllButton] frame]),
165 NSMinX([[tray_ pauseButton] frame]));
167 // Add a notification.
168 scoped_ptr<message_center::Notification> notification;
169 notification.reset(new message_center::Notification(
170 message_center::NOTIFICATION_TYPE_SIMPLE,
172 ASCIIToUTF16("First notification"),
173 ASCIIToUTF16("This is a simple test."),
177 message_center::RichNotificationData(),
179 center_->AddNotification(notification.Pass());
180 [tray_ onMessageCenterTrayChanged];
182 // Clear all should now be visible.
183 EXPECT_FALSE([[tray_ clearAllButton] isHidden]);
184 EXPECT_GT(NSMinX([[tray_ clearAllButton] frame]),
185 NSMinX([[tray_ pauseButton] frame]));
187 // Adding a second notification should keep things still visible.
188 notification.reset(new message_center::Notification(
189 message_center::NOTIFICATION_TYPE_SIMPLE,
191 ASCIIToUTF16("Second notification"),
192 ASCIIToUTF16("This is a simple test."),
196 message_center::RichNotificationData(),
198 center_->AddNotification(notification.Pass());
199 [tray_ onMessageCenterTrayChanged];
200 EXPECT_FALSE([[tray_ clearAllButton] isHidden]);
201 EXPECT_GT(NSMinX([[tray_ clearAllButton] frame]),
202 NSMinX([[tray_ pauseButton] frame]));
204 // Clear all notifications.
205 [tray_ clearAllNotifications:nil];
206 WaitForAnimationEnded();
207 [tray_ onMessageCenterTrayChanged];
209 // The button should be hidden again.
210 EXPECT_TRUE([[tray_ clearAllButton] isHidden]);
211 EXPECT_LT(NSMinX([[tray_ clearAllButton] frame]),
212 NSMinX([[tray_ pauseButton] frame]));
217 Notifier* NewNotifier(const std::string& id,
218 const std::string& title,
220 NotifierId notifier_id(NotifierId::APPLICATION, id);
221 return new Notifier(notifier_id, base::UTF8ToUTF16(title), enabled);
227 TEST_F(TrayViewControllerTest, Settings) {
228 std::vector<Notifier*> notifiers;
229 notifiers.push_back(NewNotifier("id", "title", /*enabled=*/true));
230 notifiers.push_back(NewNotifier("id2", "other title", /*enabled=*/false));
232 FakeNotifierSettingsProvider provider(notifiers);
233 center_->SetNotifierSettingsProvider(&provider);
235 CGFloat trayHeight = NSHeight([[tray_ view] frame]);
236 EXPECT_EQ(0, provider.closed_called_count());
238 [tray_ showSettings:nil];
239 EXPECT_FALSE(center_->IsMessageCenterVisible());
241 // There are 0 notifications, but 2 notifiers. The settings pane should be
242 // higher than the empty tray bubble.
243 EXPECT_LT(trayHeight, NSHeight([[tray_ view] frame]));
245 [tray_ showMessages:nil];
246 EXPECT_EQ(1, provider.closed_called_count());
247 EXPECT_TRUE(center_->IsMessageCenterVisible());
249 // The tray should be back at its previous height now.
250 EXPECT_EQ(trayHeight, NSHeight([[tray_ view] frame]));
252 // Clean up since this frame owns FakeNotifierSettingsProvider.
253 center_->SetNotifierSettingsProvider(NULL);
256 TEST_F(TrayViewControllerTest, EmptyCenter) {
257 EXPECT_FALSE([[tray_ emptyDescription] isHidden]);
259 // With no notifications, the divider should be hidden.
260 EXPECT_TRUE([[tray_ divider] isHidden]);
261 EXPECT_TRUE([[tray_ scrollView] isHidden]);
263 scoped_ptr<message_center::Notification> notification;
264 notification.reset(new message_center::Notification(
265 message_center::NOTIFICATION_TYPE_SIMPLE,
267 ASCIIToUTF16("First notification"),
268 ASCIIToUTF16("This is a simple test."),
272 message_center::RichNotificationData(),
274 center_->AddNotification(notification.Pass());
275 [tray_ onMessageCenterTrayChanged];
277 EXPECT_FALSE([[tray_ divider] isHidden]);
278 EXPECT_FALSE([[tray_ scrollView] isHidden]);
279 EXPECT_TRUE([[tray_ emptyDescription] isHidden]);
282 } // namespace message_center