1 // Copyright 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.
7 #include "base/logging.h"
8 #include "base/memory/scoped_ptr.h"
9 #include "base/strings/utf_string_conversions.h"
10 #include "testing/gtest/include/gtest/gtest.h"
11 #include "ui/message_center/fake_message_center.h"
12 #include "ui/message_center/notification.h"
13 #include "ui/message_center/notification_list.h"
14 #include "ui/message_center/notification_types.h"
15 #include "ui/message_center/views/message_center_controller.h"
16 #include "ui/message_center/views/message_center_view.h"
17 #include "ui/message_center/views/notification_view.h"
19 namespace message_center
{
21 /* Types **********************************************************************/
29 /* Instrumented/Mock NotificationView subclass ********************************/
31 class MockNotificationView
: public NotificationView
{
35 virtual void RegisterCall(CallType type
) = 0;
38 explicit MockNotificationView(MessageCenterController
* controller
,
39 const Notification
& notification
,
41 virtual ~MockNotificationView();
43 virtual gfx::Size
GetPreferredSize() OVERRIDE
;
44 virtual int GetHeightForWidth(int w
) OVERRIDE
;
45 virtual void Layout() OVERRIDE
;
50 DISALLOW_COPY_AND_ASSIGN(MockNotificationView
);
53 MockNotificationView::MockNotificationView(MessageCenterController
* controller
,
54 const Notification
& notification
,
56 : NotificationView(controller
, notification
, true),
60 MockNotificationView::~MockNotificationView() {
63 gfx::Size
MockNotificationView::GetPreferredSize() {
64 test_
->RegisterCall(GET_PREFERRED_SIZE
);
65 DCHECK(child_count() > 0);
66 return NotificationView::GetPreferredSize();
69 int MockNotificationView::GetHeightForWidth(int width
) {
70 test_
->RegisterCall(GET_HEIGHT_FOR_WIDTH
);
71 DCHECK(child_count() > 0);
72 return NotificationView::GetHeightForWidth(width
);
75 void MockNotificationView::Layout() {
76 test_
->RegisterCall(LAYOUT
);
77 DCHECK(child_count() > 0);
78 NotificationView::Layout();
81 /* Test fixture ***************************************************************/
83 class MessageCenterViewTest
: public testing::Test
,
84 public MockNotificationView::Test
,
85 public MessageCenterController
{
87 MessageCenterViewTest();
88 virtual ~MessageCenterViewTest();
90 virtual void SetUp() OVERRIDE
;
91 virtual void TearDown() OVERRIDE
;
93 MessageCenterView
* GetMessageCenterView();
94 int GetNotificationCount();
95 int GetCallCount(CallType type
);
97 // Overridden from MessageCenterController:
98 virtual void ClickOnNotification(const std::string
& notification_id
) OVERRIDE
;
99 virtual void RemoveNotification(const std::string
& notification_id
,
100 bool by_user
) OVERRIDE
;
101 virtual scoped_ptr
<ui::MenuModel
> CreateMenuModel(
102 const NotifierId
& notifier_id
,
103 const base::string16
& display_source
) OVERRIDE
;
104 virtual bool HasClickedListener(const std::string
& notification_id
) OVERRIDE
;
105 virtual void ClickOnNotificationButton(const std::string
& notification_id
,
106 int button_index
) OVERRIDE
;
107 virtual void ExpandNotification(const std::string
& notification_id
) OVERRIDE
;
109 // Overridden from MockNotificationView::Test
110 virtual void RegisterCall(CallType type
) OVERRIDE
;
112 void LogBounds(int depth
, views::View
* view
);
115 views::View
* MakeParent(views::View
* child1
, views::View
* child2
);
118 scoped_ptr
<MessageCenterView
> message_center_view_
;
119 FakeMessageCenter message_center_
;
120 std::map
<CallType
,int> callCounts_
;
122 DISALLOW_COPY_AND_ASSIGN(MessageCenterViewTest
);
125 MessageCenterViewTest::MessageCenterViewTest() {
128 MessageCenterViewTest::~MessageCenterViewTest() {
131 void MessageCenterViewTest::SetUp() {
132 // Create a dummy notification.
133 Notification
notification(NOTIFICATION_TYPE_SIMPLE
,
134 std::string("notification id"),
135 base::UTF8ToUTF16("title"),
136 base::UTF8ToUTF16("message"),
138 base::UTF8ToUTF16("display source"),
139 NotifierId(NotifierId::APPLICATION
, "extension_id"),
140 message_center::RichNotificationData(),
143 // ...and a list for it.
144 NotificationList::Notifications notifications
;
145 notifications
.insert(¬ification
);
147 // Then create a new MessageCenterView with that single notification.
148 message_center_view_
.reset(new MessageCenterView(
149 &message_center_
, NULL
, 100, false, /*top_down =*/false));
150 message_center_view_
->SetNotifications(notifications
);
152 // Remove and delete the NotificationView now owned by the MessageCenterView's
153 // MessageListView and replace it with an instrumented MockNotificationView
154 // that will become owned by the MessageListView.
155 MockNotificationView
* mock
;
156 mock
= new MockNotificationView(this, notification
, this);
157 message_center_view_
->notification_views_
[notification
.id()] = mock
;
158 message_center_view_
->SetNotificationViewForTest(mock
);
161 void MessageCenterViewTest::TearDown() {
162 message_center_view_
.reset();
165 MessageCenterView
* MessageCenterViewTest::GetMessageCenterView() {
166 return message_center_view_
.get();
169 int MessageCenterViewTest::GetNotificationCount() {
173 int MessageCenterViewTest::GetCallCount(CallType type
) {
174 return callCounts_
[type
];
177 void MessageCenterViewTest::ClickOnNotification(
178 const std::string
& notification_id
) {
179 // For this test, this method should not be invoked.
183 void MessageCenterViewTest::RemoveNotification(
184 const std::string
& notification_id
,
186 // For this test, this method should not be invoked.
190 scoped_ptr
<ui::MenuModel
> MessageCenterViewTest::CreateMenuModel(
191 const NotifierId
& notifier_id
,
192 const base::string16
& display_source
) {
193 // For this test, this method should not be invoked.
195 return scoped_ptr
<ui::MenuModel
>();
198 bool MessageCenterViewTest::HasClickedListener(
199 const std::string
& notification_id
) {
203 void MessageCenterViewTest::ClickOnNotificationButton(
204 const std::string
& notification_id
,
206 // For this test, this method should not be invoked.
210 void MessageCenterViewTest::ExpandNotification(
211 const std::string
& notification_id
) {
212 // For this test, this method should not be invoked.
216 void MessageCenterViewTest::RegisterCall(CallType type
) {
217 callCounts_
[type
] += 1;
220 void MessageCenterViewTest::LogBounds(int depth
, views::View
* view
) {
221 base::string16 inset
;
222 for (int i
= 0; i
< depth
; ++i
)
223 inset
.append(base::UTF8ToUTF16(" "));
224 gfx::Rect bounds
= view
->bounds();
225 DVLOG(0) << inset
<< bounds
.width() << " x " << bounds
.height()
226 << " @ " << bounds
.x() << ", " << bounds
.y();
227 for (int i
= 0; i
< view
->child_count(); ++i
)
228 LogBounds(depth
+ 1, view
->child_at(i
));
231 /* Unit tests *****************************************************************/
233 TEST_F(MessageCenterViewTest
, CallTest
) {
234 // Exercise (with size values that just need to be large enough).
235 GetMessageCenterView()->SetBounds(0, 0, 100, 100);
237 // Verify that this didn't generate more than 2 Layout() call per descendant
238 // NotificationView or more than a total of 20 GetPreferredSize() and
239 // GetHeightForWidth() calls per descendant NotificationView. 20 is a very
240 // large number corresponding to the current reality. That number will be
241 // ratcheted down over time as the code improves.
242 EXPECT_LE(GetCallCount(LAYOUT
), GetNotificationCount() * 2);
243 EXPECT_LE(GetCallCount(GET_PREFERRED_SIZE
) +
244 GetCallCount(GET_HEIGHT_FOR_WIDTH
),
245 GetNotificationCount() * 20);
248 } // namespace message_center