message_center_view_unittest.cc revision c2e0dbddbe15c98d52c4786dac06cb8952a8ae6d
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.
4
5#include <map>
6
7#include "base/logging.h"
8#include "base/memory/scoped_ptr.h"
9#include "base/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_view.h"
16#include "ui/message_center/views/notification_view.h"
17
18namespace message_center {
19
20/* Types **********************************************************************/
21
22enum CallType {
23  GET_PREFERRED_SIZE,
24  GET_HEIGHT_FOR_WIDTH,
25  LAYOUT
26};
27
28/* Instrumented/Mock NotificationView subclass ********************************/
29
30class MockNotificationView : public NotificationView {
31 public:
32  class Test {
33   public:
34    virtual void RegisterCall(int receiver_id, CallType type) = 0;
35  };
36
37  explicit MockNotificationView(const Notification& notification,
38                                MessageCenter* message_center,
39                                Test* test,
40                                int view_id);
41  virtual ~MockNotificationView();
42
43  virtual gfx::Size GetPreferredSize() OVERRIDE;
44  virtual int GetHeightForWidth(int w) OVERRIDE;
45  virtual void Layout() OVERRIDE;
46
47  int get_id() { return id_; };
48
49 private:
50  void RegisterCall(CallType type);
51
52  Test* test_;
53  int id_;
54
55  DISALLOW_COPY_AND_ASSIGN(MockNotificationView);
56};
57
58MockNotificationView::MockNotificationView(const Notification& notification,
59                                           MessageCenter* message_center,
60                                           Test* test,
61                                           int view_id)
62    : NotificationView(notification, message_center, true),
63      test_(test),
64      id_(view_id) {
65}
66
67MockNotificationView::~MockNotificationView() {
68}
69
70gfx::Size MockNotificationView::GetPreferredSize() {
71  RegisterCall(GET_PREFERRED_SIZE);
72  return child_count() ? NotificationView::GetPreferredSize() :
73                         gfx::Size(id_, id_);
74}
75
76int MockNotificationView::GetHeightForWidth(int width) {
77  RegisterCall(GET_HEIGHT_FOR_WIDTH);
78  return child_count() ? NotificationView::GetHeightForWidth(width) : (id_);
79}
80
81void MockNotificationView::Layout() {
82  RegisterCall(LAYOUT);
83  if (child_count())
84    NotificationView::Layout();
85}
86
87void MockNotificationView::RegisterCall(CallType type) {
88  if (test_)
89    test_->RegisterCall(id_, type);
90}
91
92/* Test fixture ***************************************************************/
93
94class MessageCenterViewTest : public testing::Test,
95                              public MockNotificationView::Test {
96 public:
97  MessageCenterViewTest();
98  virtual ~MessageCenterViewTest();
99
100  virtual void SetUp() OVERRIDE;
101  virtual void TearDown() OVERRIDE;
102
103  MessageCenterView* GetMessageCenterView();
104  int GetNotificationCount();
105  int GetCallCount(CallType type);
106
107  virtual void RegisterCall(int receiver_id, CallType type) OVERRIDE;
108
109  void LogBounds(int depth, views::View* view);
110
111 private:
112  views::View* MakeParent(views::View* child1, views::View* child2);
113
114
115  scoped_ptr<MessageCenterView> message_center_view_;
116  FakeMessageCenter message_center_;
117  std::map<CallType,int> callCounts_;
118
119  DISALLOW_COPY_AND_ASSIGN(MessageCenterViewTest);
120};
121
122MessageCenterViewTest::MessageCenterViewTest() {
123}
124
125MessageCenterViewTest::~MessageCenterViewTest() {
126}
127
128void MessageCenterViewTest::SetUp() {
129  // Create a dummy notification.
130  Notification notification(
131        NOTIFICATION_TYPE_SIMPLE,
132        std::string("notification id"),
133        UTF8ToUTF16("title"),
134        UTF8ToUTF16("message"),
135        UTF8ToUTF16("display source"),
136        std::string("extension id"),
137        NULL);
138
139  // ...and a list for it.
140  NotificationList::Notifications notifications;
141  notifications.insert(&notification);
142
143  // Then create a new MessageCenterView with that single notification.
144  message_center_view_.reset(new MessageCenterView(&message_center_, 100));
145  message_center_view_->SetNotifications(notifications);
146
147  // Remove and delete the NotificationView now owned by the MessageCenterView's
148  // MessageListView and replace it with an instrumented MockNotificationView
149  // that will become owned by the MessageListView.
150  MockNotificationView* mock;
151  mock = new MockNotificationView(notification, &message_center_, this, 42);
152  message_center_view_->message_views_.push_back(mock);
153  message_center_view_->SetNotificationViewForTest(mock);
154}
155
156void MessageCenterViewTest::TearDown() {
157  message_center_view_.reset();
158}
159
160MessageCenterView* MessageCenterViewTest::GetMessageCenterView() {
161  return message_center_view_.get();
162}
163
164int MessageCenterViewTest::GetNotificationCount() {
165  return 1;
166}
167
168int MessageCenterViewTest::GetCallCount(CallType type) {
169  return callCounts_[type];
170}
171
172void MessageCenterViewTest::RegisterCall(int receiver_id, CallType type) {
173  callCounts_[type] += 1;
174}
175
176void MessageCenterViewTest::LogBounds(int depth, views::View* view) {
177  string16 inset;
178  for (int i = 0; i < depth; ++i)
179    inset.append(UTF8ToUTF16("  "));
180  gfx::Rect bounds = view->bounds();
181  DVLOG(0) << inset << bounds.width() << " x " << bounds.height()
182           << " @ " << bounds.x() << ", " << bounds.y();
183  for (int i = 0; i < view->child_count(); ++i)
184    LogBounds(depth + 1, view->child_at(i));
185}
186
187/* Unit tests *****************************************************************/
188
189TEST_F(MessageCenterViewTest, CallTest) {
190  // Exercise (with size values that just need to be large enough).
191  GetMessageCenterView()->SetBounds(0, 0, 100, 100);
192
193  // Verify that this didn't generate more than 2 Layout() call per descendant
194  // NotificationView or more than a total of 20 GetPreferredSize() and
195  // GetHeightForWidth() calls per descendant NotificationView. 20 is a very
196  // large number corresponding to the current reality. That number will be
197  // ratcheted down over time as the code improves.
198  EXPECT_LE(GetCallCount(LAYOUT), GetNotificationCount() * 2);
199  EXPECT_LE(GetCallCount(GET_PREFERRED_SIZE) +
200            GetCallCount(GET_HEIGHT_FOR_WIDTH),
201            GetNotificationCount() * 20);
202}
203
204}  // namespace message_center
205