• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/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"
18 
19 namespace message_center {
20 
21 /* Types **********************************************************************/
22 
23 enum CallType {
24   GET_PREFERRED_SIZE,
25   GET_HEIGHT_FOR_WIDTH,
26   LAYOUT
27 };
28 
29 /* Instrumented/Mock NotificationView subclass ********************************/
30 
31 class MockNotificationView : public NotificationView {
32  public:
33   class Test {
34    public:
35     virtual void RegisterCall(CallType type) = 0;
36   };
37 
38   explicit MockNotificationView(MessageCenterController* controller,
39                                 const Notification& notification,
40                                 Test* test);
41   virtual ~MockNotificationView();
42 
43   virtual gfx::Size GetPreferredSize() OVERRIDE;
44   virtual int GetHeightForWidth(int w) OVERRIDE;
45   virtual void Layout() OVERRIDE;
46 
47  private:
48   Test* test_;
49 
50   DISALLOW_COPY_AND_ASSIGN(MockNotificationView);
51 };
52 
MockNotificationView(MessageCenterController * controller,const Notification & notification,Test * test)53 MockNotificationView::MockNotificationView(MessageCenterController* controller,
54                                            const Notification& notification,
55                                            Test* test)
56     : NotificationView(controller, notification, true),
57       test_(test) {
58 }
59 
~MockNotificationView()60 MockNotificationView::~MockNotificationView() {
61 }
62 
GetPreferredSize()63 gfx::Size MockNotificationView::GetPreferredSize() {
64   test_->RegisterCall(GET_PREFERRED_SIZE);
65   DCHECK(child_count() > 0);
66   return NotificationView::GetPreferredSize();
67 }
68 
GetHeightForWidth(int width)69 int MockNotificationView::GetHeightForWidth(int width) {
70   test_->RegisterCall(GET_HEIGHT_FOR_WIDTH);
71   DCHECK(child_count() > 0);
72   return NotificationView::GetHeightForWidth(width);
73 }
74 
Layout()75 void MockNotificationView::Layout() {
76   test_->RegisterCall(LAYOUT);
77   DCHECK(child_count() > 0);
78   NotificationView::Layout();
79 }
80 
81 /* Test fixture ***************************************************************/
82 
83 class MessageCenterViewTest : public testing::Test,
84                               public MockNotificationView::Test,
85                               public MessageCenterController {
86  public:
87   MessageCenterViewTest();
88   virtual ~MessageCenterViewTest();
89 
90   virtual void SetUp() OVERRIDE;
91   virtual void TearDown() OVERRIDE;
92 
93   MessageCenterView* GetMessageCenterView();
94   int GetNotificationCount();
95   int GetCallCount(CallType type);
96 
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 void DisableNotificationsFromThisSource(
102       const NotifierId& notifier_id) OVERRIDE;
103   virtual void ShowNotifierSettingsBubble() 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;
108   virtual void GroupBodyClicked(const std::string& last_notification_id)
109       OVERRIDE;
110   virtual void ExpandGroup(const NotifierId& notifier_id) OVERRIDE;
111   virtual void RemoveGroup(const NotifierId& notifier_id) OVERRIDE;
112 
113   // Overridden from MockNotificationView::Test
114   virtual void RegisterCall(CallType type) OVERRIDE;
115 
116   void LogBounds(int depth, views::View* view);
117 
118  private:
119   views::View* MakeParent(views::View* child1, views::View* child2);
120 
121 
122   scoped_ptr<MessageCenterView> message_center_view_;
123   FakeMessageCenter message_center_;
124   std::map<CallType,int> callCounts_;
125 
126   DISALLOW_COPY_AND_ASSIGN(MessageCenterViewTest);
127 };
128 
MessageCenterViewTest()129 MessageCenterViewTest::MessageCenterViewTest() {
130 }
131 
~MessageCenterViewTest()132 MessageCenterViewTest::~MessageCenterViewTest() {
133 }
134 
SetUp()135 void MessageCenterViewTest::SetUp() {
136   // Create a dummy notification.
137   Notification notification(NOTIFICATION_TYPE_SIMPLE,
138                             std::string("notification id"),
139                             UTF8ToUTF16("title"),
140                             UTF8ToUTF16("message"),
141                             gfx::Image(),
142                             UTF8ToUTF16("display source"),
143                             NotifierId(NotifierId::APPLICATION, "extension_id"),
144                             message_center::RichNotificationData(),
145                             NULL);
146 
147   // ...and a list for it.
148   NotificationList::Notifications notifications;
149   notifications.insert(&notification);
150 
151   // Then create a new MessageCenterView with that single notification.
152   message_center_view_.reset(new MessageCenterView(
153       &message_center_, NULL, 100, false, /*top_down =*/false));
154   message_center_view_->SetNotifications(notifications);
155 
156   // Remove and delete the NotificationView now owned by the MessageCenterView's
157   // MessageListView and replace it with an instrumented MockNotificationView
158   // that will become owned by the MessageListView.
159   MockNotificationView* mock;
160   mock = new MockNotificationView(this, notification, this);
161   message_center_view_->notification_views_[notification.id()] = mock;
162   message_center_view_->SetNotificationViewForTest(mock);
163 }
164 
TearDown()165 void MessageCenterViewTest::TearDown() {
166   message_center_view_.reset();
167 }
168 
GetMessageCenterView()169 MessageCenterView* MessageCenterViewTest::GetMessageCenterView() {
170   return message_center_view_.get();
171 }
172 
GetNotificationCount()173 int MessageCenterViewTest::GetNotificationCount() {
174   return 1;
175 }
176 
GetCallCount(CallType type)177 int MessageCenterViewTest::GetCallCount(CallType type) {
178   return callCounts_[type];
179 }
180 
ClickOnNotification(const std::string & notification_id)181 void MessageCenterViewTest::ClickOnNotification(
182     const std::string& notification_id) {
183   // For this test, this method should not be invoked.
184   NOTREACHED();
185 }
186 
RemoveNotification(const std::string & notification_id,bool by_user)187 void MessageCenterViewTest::RemoveNotification(
188     const std::string& notification_id,
189     bool by_user) {
190   // For this test, this method should not be invoked.
191   NOTREACHED();
192 }
193 
DisableNotificationsFromThisSource(const NotifierId & notifier_id)194 void MessageCenterViewTest::DisableNotificationsFromThisSource(
195     const NotifierId& notifier_id) {
196   // For this test, this method should not be invoked.
197   NOTREACHED();
198 }
199 
ShowNotifierSettingsBubble()200 void MessageCenterViewTest::ShowNotifierSettingsBubble() {
201   // For this test, this method should not be invoked.
202   NOTREACHED();
203 }
204 
HasClickedListener(const std::string & notification_id)205 bool MessageCenterViewTest::HasClickedListener(
206     const std::string& notification_id) {
207   return true;
208 }
209 
ClickOnNotificationButton(const std::string & notification_id,int button_index)210 void MessageCenterViewTest::ClickOnNotificationButton(
211     const std::string& notification_id,
212     int button_index) {
213   // For this test, this method should not be invoked.
214   NOTREACHED();
215 }
216 
ExpandNotification(const std::string & notification_id)217 void MessageCenterViewTest::ExpandNotification(
218     const std::string& notification_id) {
219   // For this test, this method should not be invoked.
220   NOTREACHED();
221 }
222 
GroupBodyClicked(const std::string & last_notification_id)223 void MessageCenterViewTest::GroupBodyClicked(
224     const std::string& last_notification_id) {
225   // For this test, this method should not be invoked.
226   NOTREACHED();
227 }
228 
ExpandGroup(const NotifierId & notifier_id)229 void MessageCenterViewTest::ExpandGroup(const NotifierId& notifier_id) {
230   // For this test, this method should not be invoked.
231   NOTREACHED();
232 }
233 
RemoveGroup(const NotifierId & notifier_id)234 void MessageCenterViewTest::RemoveGroup(const NotifierId& notifier_id) {
235   // For this test, this method should not be invoked.
236   NOTREACHED();
237 }
238 
RegisterCall(CallType type)239 void MessageCenterViewTest::RegisterCall(CallType type) {
240   callCounts_[type] += 1;
241 }
242 
LogBounds(int depth,views::View * view)243 void MessageCenterViewTest::LogBounds(int depth, views::View* view) {
244   string16 inset;
245   for (int i = 0; i < depth; ++i)
246     inset.append(UTF8ToUTF16("  "));
247   gfx::Rect bounds = view->bounds();
248   DVLOG(0) << inset << bounds.width() << " x " << bounds.height()
249            << " @ " << bounds.x() << ", " << bounds.y();
250   for (int i = 0; i < view->child_count(); ++i)
251     LogBounds(depth + 1, view->child_at(i));
252 }
253 
254 /* Unit tests *****************************************************************/
255 
TEST_F(MessageCenterViewTest,CallTest)256 TEST_F(MessageCenterViewTest, CallTest) {
257   // Exercise (with size values that just need to be large enough).
258   GetMessageCenterView()->SetBounds(0, 0, 100, 100);
259 
260   // Verify that this didn't generate more than 2 Layout() call per descendant
261   // NotificationView or more than a total of 20 GetPreferredSize() and
262   // GetHeightForWidth() calls per descendant NotificationView. 20 is a very
263   // large number corresponding to the current reality. That number will be
264   // ratcheted down over time as the code improves.
265   EXPECT_LE(GetCallCount(LAYOUT), GetNotificationCount() * 2);
266   EXPECT_LE(GetCallCount(GET_PREFERRED_SIZE) +
267             GetCallCount(GET_HEIGHT_FOR_WIDTH),
268             GetNotificationCount() * 20);
269 }
270 
271 }  // namespace message_center
272