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, "1",
76 ASCIIToUTF16("First notification"),
77 ASCIIToUTF16("This is a simple test."), gfx::Image(), base::string16(),
78 GURL(), DummyNotifierId(), message_center::RichNotificationData(), NULL));
79 center_->AddNotification(notification_data.Pass());
80 [tray_ onMessageCenterTrayChanged];
81 ASSERT_EQ(1u, [[view subviews] count]);
83 // The view should have padding around it.
84 NSView* notification = [[view subviews] objectAtIndex:0];
85 NSRect notification_frame = [notification frame];
86 EXPECT_CGFLOAT_EQ(2 * message_center::kMarginBetweenItems,
87 NSHeight([view frame]) - NSHeight(notification_frame));
88 EXPECT_CGFLOAT_EQ(2 * message_center::kMarginBetweenItems,
89 NSWidth([view frame]) - NSWidth(notification_frame));
90 EXPECT_GT(NSHeight([[tray_ view] frame]),
91 NSHeight([[tray_ scrollView] frame]));
93 center_->RemoveNotification("1", true);
94 [tray_ onMessageCenterTrayChanged];
95 EXPECT_EQ(0u, [[view subviews] count]);
96 // The empty tray is now 100px tall to accommodate
98 EXPECT_CGFLOAT_EQ(message_center::kMinScrollViewHeight,
99 NSHeight([view frame]));
102 TEST_F(TrayViewControllerTest, AddThreeClearAll) {
103 NSScrollView* view = [[tray_ scrollView] documentView];
104 EXPECT_EQ(0u, [[view subviews] count]);
105 scoped_ptr<message_center::Notification> notification;
106 notification.reset(new message_center::Notification(
107 message_center::NOTIFICATION_TYPE_SIMPLE, "1",
108 ASCIIToUTF16("First notification"),
109 ASCIIToUTF16("This is a simple test."), gfx::Image(), base::string16(),
110 GURL(), DummyNotifierId(), message_center::RichNotificationData(), NULL));
111 center_->AddNotification(notification.Pass());
112 notification.reset(new message_center::Notification(
113 message_center::NOTIFICATION_TYPE_SIMPLE, "2",
114 ASCIIToUTF16("Second notification"),
115 ASCIIToUTF16("This is a simple test."), gfx::Image(), base::string16(),
116 GURL(), DummyNotifierId(), message_center::RichNotificationData(), NULL));
117 center_->AddNotification(notification.Pass());
118 notification.reset(new message_center::Notification(
119 message_center::NOTIFICATION_TYPE_SIMPLE, "3",
120 ASCIIToUTF16("Third notification"),
121 ASCIIToUTF16("This is a simple test."), gfx::Image(), base::string16(),
122 GURL(), DummyNotifierId(), message_center::RichNotificationData(), NULL));
123 center_->AddNotification(notification.Pass());
124 [tray_ onMessageCenterTrayChanged];
125 ASSERT_EQ(3u, [[view subviews] count]);
127 [tray_ clearAllNotifications:nil];
128 WaitForAnimationEnded();
129 [tray_ onMessageCenterTrayChanged];
131 EXPECT_EQ(0u, [[view subviews] count]);
132 // The empty tray is now 100px tall to accommodate
133 // the empty message.
134 EXPECT_CGFLOAT_EQ(message_center::kMinScrollViewHeight,
135 NSHeight([view frame]));
138 TEST_F(TrayViewControllerTest, NoClearAllWhenNoNotifications) {
139 EXPECT_TRUE([tray_ pauseButton]);
140 EXPECT_TRUE([tray_ clearAllButton]);
142 // With no notifications, the clear all button should be hidden.
143 EXPECT_TRUE([[tray_ clearAllButton] isHidden]);
144 EXPECT_LT(NSMinX([[tray_ clearAllButton] frame]),
145 NSMinX([[tray_ pauseButton] frame]));
147 // Add a notification.
148 scoped_ptr<message_center::Notification> notification;
149 notification.reset(new message_center::Notification(
150 message_center::NOTIFICATION_TYPE_SIMPLE, "1",
151 ASCIIToUTF16("First notification"),
152 ASCIIToUTF16("This is a simple test."), gfx::Image(), base::string16(),
153 GURL(), DummyNotifierId(), message_center::RichNotificationData(), NULL));
154 center_->AddNotification(notification.Pass());
155 [tray_ onMessageCenterTrayChanged];
157 // Clear all should now be visible.
158 EXPECT_FALSE([[tray_ clearAllButton] isHidden]);
159 EXPECT_GT(NSMinX([[tray_ clearAllButton] frame]),
160 NSMinX([[tray_ pauseButton] frame]));
162 // Adding a second notification should keep things still visible.
163 notification.reset(new message_center::Notification(
164 message_center::NOTIFICATION_TYPE_SIMPLE, "2",
165 ASCIIToUTF16("Second notification"),
166 ASCIIToUTF16("This is a simple test."), gfx::Image(), base::string16(),
167 GURL(), DummyNotifierId(), message_center::RichNotificationData(), NULL));
168 center_->AddNotification(notification.Pass());
169 [tray_ onMessageCenterTrayChanged];
170 EXPECT_FALSE([[tray_ clearAllButton] isHidden]);
171 EXPECT_GT(NSMinX([[tray_ clearAllButton] frame]),
172 NSMinX([[tray_ pauseButton] frame]));
174 // Clear all notifications.
175 [tray_ clearAllNotifications:nil];
176 WaitForAnimationEnded();
177 [tray_ onMessageCenterTrayChanged];
179 // The button should be hidden again.
180 EXPECT_TRUE([[tray_ clearAllButton] isHidden]);
181 EXPECT_LT(NSMinX([[tray_ clearAllButton] frame]),
182 NSMinX([[tray_ pauseButton] frame]));
187 Notifier* NewNotifier(const std::string& id,
188 const std::string& title,
190 NotifierId notifier_id(NotifierId::APPLICATION, id);
191 return new Notifier(notifier_id, base::UTF8ToUTF16(title), enabled);
197 TEST_F(TrayViewControllerTest, Settings) {
198 std::vector<Notifier*> notifiers;
199 notifiers.push_back(NewNotifier("id", "title", /*enabled=*/true));
200 notifiers.push_back(NewNotifier("id2", "other title", /*enabled=*/false));
202 FakeNotifierSettingsProvider provider(notifiers);
203 center_->SetNotifierSettingsProvider(&provider);
205 CGFloat trayHeight = NSHeight([[tray_ view] frame]);
206 EXPECT_EQ(0, provider.closed_called_count());
208 [tray_ showSettings:nil];
209 EXPECT_FALSE(center_->IsMessageCenterVisible());
211 // There are 0 notifications, but 2 notifiers. The settings pane should be
212 // higher than the empty tray bubble.
213 EXPECT_LT(trayHeight, NSHeight([[tray_ view] frame]));
215 [tray_ showMessages:nil];
216 EXPECT_EQ(1, provider.closed_called_count());
217 EXPECT_TRUE(center_->IsMessageCenterVisible());
219 // The tray should be back at its previous height now.
220 EXPECT_EQ(trayHeight, NSHeight([[tray_ view] frame]));
222 // Clean up since this frame owns FakeNotifierSettingsProvider.
223 center_->SetNotifierSettingsProvider(NULL);
226 TEST_F(TrayViewControllerTest, EmptyCenter) {
227 EXPECT_FALSE([[tray_ emptyDescription] isHidden]);
229 // With no notifications, the divider should be hidden.
230 EXPECT_TRUE([[tray_ divider] isHidden]);
231 EXPECT_TRUE([[tray_ scrollView] isHidden]);
233 scoped_ptr<message_center::Notification> notification;
234 notification.reset(new message_center::Notification(
235 message_center::NOTIFICATION_TYPE_SIMPLE, "1",
236 ASCIIToUTF16("First notification"),
237 ASCIIToUTF16("This is a simple test."), gfx::Image(), base::string16(),
238 GURL(), DummyNotifierId(), message_center::RichNotificationData(), NULL));
239 center_->AddNotification(notification.Pass());
240 [tray_ onMessageCenterTrayChanged];
242 EXPECT_FALSE([[tray_ divider] isHidden]);
243 EXPECT_FALSE([[tray_ scrollView] isHidden]);
244 EXPECT_TRUE([[tray_ emptyDescription] isHidden]);
247 } // namespace message_center