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/base/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 class TrayViewControllerTest : public ui::CocoaTest {
21 TrayViewControllerTest()
23 message_loop_(base::MessageLoop::TYPE_UI) {
26 virtual void SetUp() OVERRIDE {
27 ui::CocoaTest::SetUp();
28 message_center::MessageCenter::Initialize();
29 center_ = message_center::MessageCenter::Get();
30 center_->DisableTimersForTest();
31 tray_.reset([[MCTrayViewController alloc] initWithMessageCenter:center_]);
32 [tray_ setAnimationDuration:0.002];
33 [tray_ setAnimateClearingNextNotificationDelay:0.001];
34 [tray_ setAnimationEndedCallback:^{
35 if (nested_run_loop_.get())
36 nested_run_loop_->Quit();
38 [tray_ view]; // Create the view.
41 virtual void TearDown() OVERRIDE {
43 message_center::MessageCenter::Shutdown();
44 ui::CocoaTest::TearDown();
47 void WaitForAnimationEnded() {
48 if (![tray_ isAnimating])
50 nested_run_loop_.reset(new base::RunLoop());
51 nested_run_loop_->Run();
52 nested_run_loop_.reset();
56 message_center::MessageCenter* center_; // Weak, global.
58 base::MessageLoop message_loop_;
59 scoped_ptr<base::RunLoop> nested_run_loop_;
60 base::scoped_nsobject<MCTrayViewController> tray_;
63 TEST_F(TrayViewControllerTest, AddRemoveOne) {
64 NSScrollView* view = [[tray_ scrollView] documentView];
65 EXPECT_EQ(0u, [[view subviews] count]);
66 scoped_ptr<message_center::Notification> notification_data;
67 notification_data.reset(new message_center::Notification(
68 message_center::NOTIFICATION_TYPE_SIMPLE,
70 ASCIIToUTF16("First notification"),
71 ASCIIToUTF16("This is a simple test."),
74 message_center::NotifierId(),
75 message_center::RichNotificationData(),
77 center_->AddNotification(notification_data.Pass());
78 [tray_ onMessageCenterTrayChanged];
79 ASSERT_EQ(1u, [[view subviews] count]);
81 // The view should have padding around it.
82 NSView* notification = [[view subviews] objectAtIndex:0];
83 NSRect notification_frame = [notification frame];
84 EXPECT_CGFLOAT_EQ(2 * message_center::kMarginBetweenItems,
85 NSHeight([view frame]) - NSHeight(notification_frame));
86 EXPECT_CGFLOAT_EQ(2 * message_center::kMarginBetweenItems,
87 NSWidth([view frame]) - NSWidth(notification_frame));
88 EXPECT_GT(NSHeight([[tray_ view] frame]),
89 NSHeight([[tray_ scrollView] frame]));
91 center_->RemoveNotification("1", true);
92 [tray_ onMessageCenterTrayChanged];
93 EXPECT_EQ(0u, [[view subviews] count]);
94 EXPECT_CGFLOAT_EQ(0, NSHeight([view frame]));
97 TEST_F(TrayViewControllerTest, AddThreeClearAll) {
98 NSScrollView* view = [[tray_ scrollView] documentView];
99 EXPECT_EQ(0u, [[view subviews] count]);
100 scoped_ptr<message_center::Notification> notification;
101 notification.reset(new message_center::Notification(
102 message_center::NOTIFICATION_TYPE_SIMPLE,
104 ASCIIToUTF16("First notification"),
105 ASCIIToUTF16("This is a simple test."),
108 message_center::NotifierId(),
109 message_center::RichNotificationData(),
111 center_->AddNotification(notification.Pass());
112 notification.reset(new message_center::Notification(
113 message_center::NOTIFICATION_TYPE_SIMPLE,
115 ASCIIToUTF16("Second notification"),
116 ASCIIToUTF16("This is a simple test."),
119 message_center::NotifierId(),
120 message_center::RichNotificationData(),
122 center_->AddNotification(notification.Pass());
123 notification.reset(new message_center::Notification(
124 message_center::NOTIFICATION_TYPE_SIMPLE,
126 ASCIIToUTF16("Third notification"),
127 ASCIIToUTF16("This is a simple test."),
130 message_center::NotifierId(),
131 message_center::RichNotificationData(),
133 center_->AddNotification(notification.Pass());
134 [tray_ onMessageCenterTrayChanged];
135 ASSERT_EQ(3u, [[view subviews] count]);
137 [tray_ clearAllNotifications:nil];
138 WaitForAnimationEnded();
139 [tray_ onMessageCenterTrayChanged];
141 EXPECT_EQ(0u, [[view subviews] count]);
142 EXPECT_CGFLOAT_EQ(0, NSHeight([view frame]));
145 TEST_F(TrayViewControllerTest, NoClearAllWhenNoNotifications) {
146 EXPECT_TRUE([tray_ pauseButton]);
147 EXPECT_TRUE([tray_ clearAllButton]);
149 // With no notifications, the clear all button should be hidden.
150 EXPECT_TRUE([[tray_ clearAllButton] isHidden]);
151 EXPECT_LT(NSMinX([[tray_ clearAllButton] frame]),
152 NSMinX([[tray_ pauseButton] frame]));
154 // Add a notification.
155 scoped_ptr<message_center::Notification> notification;
156 notification.reset(new message_center::Notification(
157 message_center::NOTIFICATION_TYPE_SIMPLE,
159 ASCIIToUTF16("First notification"),
160 ASCIIToUTF16("This is a simple test."),
163 message_center::NotifierId(),
164 message_center::RichNotificationData(),
166 center_->AddNotification(notification.Pass());
167 [tray_ onMessageCenterTrayChanged];
169 // Clear all should now be visible.
170 EXPECT_FALSE([[tray_ clearAllButton] isHidden]);
171 EXPECT_GT(NSMinX([[tray_ clearAllButton] frame]),
172 NSMinX([[tray_ pauseButton] frame]));
174 // Adding a second notification should keep things still visible.
175 notification.reset(new message_center::Notification(
176 message_center::NOTIFICATION_TYPE_SIMPLE,
178 ASCIIToUTF16("Second notification"),
179 ASCIIToUTF16("This is a simple test."),
182 message_center::NotifierId(),
183 message_center::RichNotificationData(),
185 center_->AddNotification(notification.Pass());
186 [tray_ onMessageCenterTrayChanged];
187 EXPECT_FALSE([[tray_ clearAllButton] isHidden]);
188 EXPECT_GT(NSMinX([[tray_ clearAllButton] frame]),
189 NSMinX([[tray_ pauseButton] frame]));
191 // Clear all notifications.
192 [tray_ clearAllNotifications:nil];
193 WaitForAnimationEnded();
194 [tray_ onMessageCenterTrayChanged];
196 // The button should be hidden again.
197 EXPECT_TRUE([[tray_ clearAllButton] isHidden]);
198 EXPECT_LT(NSMinX([[tray_ clearAllButton] frame]),
199 NSMinX([[tray_ pauseButton] frame]));
202 namespace message_center {
206 Notifier* NewNotifier(const std::string& id,
207 const std::string& title,
209 NotifierId notifier_id(NotifierId::APPLICATION, id);
210 return new Notifier(notifier_id, base::UTF8ToUTF16(title), enabled);
216 TEST_F(TrayViewControllerTest, Settings) {
217 std::vector<Notifier*> notifiers;
218 notifiers.push_back(NewNotifier("id", "title", /*enabled=*/true));
219 notifiers.push_back(NewNotifier("id2", "other title", /*enabled=*/false));
221 FakeNotifierSettingsProvider provider(notifiers);
222 center_->SetNotifierSettingsProvider(&provider);
224 CGFloat trayHeight = NSHeight([[tray_ view] frame]);
225 EXPECT_EQ(0, provider.closed_called_count());
227 [tray_ showSettings:nil];
228 EXPECT_FALSE(center_->IsMessageCenterVisible());
230 // There are 0 notifications, but 2 notifiers. The settings pane should be
231 // higher than the empty tray bubble.
232 EXPECT_LT(trayHeight, NSHeight([[tray_ view] frame]));
234 [tray_ showMessages:nil];
235 EXPECT_EQ(1, provider.closed_called_count());
236 EXPECT_TRUE(center_->IsMessageCenterVisible());
238 // The tray should be back at its previous height now.
239 EXPECT_EQ(trayHeight, NSHeight([[tray_ view] frame]));
242 } // namespace message_center