Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / ui / message_center / views / notification_view_unittest.cc
1 // Copyright 2014 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 "ui/message_center/views/notification_view.h"
6
7 #include "base/memory/scoped_ptr.h"
8 #include "base/strings/utf_string_conversions.h"
9 #include "testing/gtest/include/gtest/gtest.h"
10 #include "third_party/skia/include/core/SkBitmap.h"
11 #include "ui/gfx/image/image.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/notification_button.h"
17 #include "ui/views/layout/fill_layout.h"
18 #include "ui/views/test/views_test_base.h"
19 #include "ui/views/widget/widget_delegate.h"
20
21 namespace message_center {
22
23 /* Test fixture ***************************************************************/
24
25 class NotificationViewTest : public views::ViewsTestBase,
26                              public MessageCenterController {
27  public:
28   NotificationViewTest();
29   ~NotificationViewTest() override;
30
31   void SetUp() override;
32   void TearDown() override;
33
34   views::Widget* widget() { return notification_view_->GetWidget(); }
35   NotificationView* notification_view() { return notification_view_.get(); }
36   Notification* notification() { return notification_.get(); }
37   RichNotificationData* data() { return data_.get(); }
38
39   // Overridden from MessageCenterController:
40   void ClickOnNotification(const std::string& notification_id) override;
41   void RemoveNotification(const std::string& notification_id,
42                           bool by_user) override;
43   scoped_ptr<ui::MenuModel> CreateMenuModel(
44       const NotifierId& notifier_id,
45       const base::string16& display_source) override;
46   bool HasClickedListener(const std::string& notification_id) override;
47   void ClickOnNotificationButton(const std::string& notification_id,
48                                  int button_index) override;
49
50  protected:
51   const gfx::Image CreateTestImage(int width, int height) {
52     return gfx::Image::CreateFrom1xBitmap(CreateBitmap(width, height));
53   }
54
55   const SkBitmap CreateBitmap(int width, int height) {
56     SkBitmap bitmap;
57     bitmap.allocN32Pixels(width, height);
58     bitmap.eraseRGB(0, 255, 0);
59     return bitmap;
60   }
61
62   std::vector<ButtonInfo> CreateButtons(int number) {
63     ButtonInfo info(base::ASCIIToUTF16("Test button title."));
64     info.icon = CreateTestImage(4, 4);
65     return std::vector<ButtonInfo>(number, info);
66   }
67
68   void CheckVerticalOrderInNotification() {
69     std::vector<views::View*> vertical_order;
70     vertical_order.push_back(notification_view()->top_view_);
71     vertical_order.push_back(notification_view()->image_view_);
72     std::copy(notification_view()->action_buttons_.begin(),
73               notification_view()->action_buttons_.end(),
74               std::back_inserter(vertical_order));
75     std::vector<views::View*>::iterator current = vertical_order.begin();
76     std::vector<views::View*>::iterator last = current++;
77     while (current != vertical_order.end()) {
78       gfx::Point last_point = (*last)->bounds().origin();
79       views::View::ConvertPointToTarget(
80           (*last), notification_view(), &last_point);
81
82       gfx::Point current_point = (*current)->bounds().origin();
83       views::View::ConvertPointToTarget(
84           (*current), notification_view(), &current_point);
85
86       EXPECT_LT(last_point.y(), current_point.y());
87       last = current++;
88     }
89   }
90
91   void UpdateNotificationViews() {
92     notification_view()->CreateOrUpdateViews(*notification());
93     notification_view()->Layout();
94   }
95
96  private:
97   scoped_ptr<RichNotificationData> data_;
98   scoped_ptr<Notification> notification_;
99   scoped_ptr<NotificationView> notification_view_;
100
101   DISALLOW_COPY_AND_ASSIGN(NotificationViewTest);
102 };
103
104 NotificationViewTest::NotificationViewTest() {
105 }
106
107 NotificationViewTest::~NotificationViewTest() {
108 }
109
110 void NotificationViewTest::SetUp() {
111   views::ViewsTestBase::SetUp();
112   // Create a dummy notification.
113   SkBitmap bitmap;
114   data_.reset(new RichNotificationData());
115   notification_.reset(
116       new Notification(NOTIFICATION_TYPE_BASE_FORMAT,
117                        std::string("notification id"),
118                        base::UTF8ToUTF16("title"),
119                        base::UTF8ToUTF16("message"),
120                        CreateTestImage(80, 80),
121                        base::UTF8ToUTF16("display source"),
122                        NotifierId(NotifierId::APPLICATION, "extension_id"),
123                        *data_,
124                        NULL));
125   notification_->set_small_image(CreateTestImage(16, 16));
126   notification_->set_image(CreateTestImage(320, 240));
127
128   // Then create a new NotificationView with that single notification.
129   notification_view_.reset(
130       NotificationView::Create(this, *notification_, true));
131   notification_view_->set_owned_by_client();
132
133   views::Widget::InitParams init_params(
134       CreateParams(views::Widget::InitParams::TYPE_POPUP));
135   views::Widget* widget = new views::Widget();
136   widget->Init(init_params);
137   widget->SetContentsView(notification_view_.get());
138   widget->SetSize(notification_view_->GetPreferredSize());
139 }
140
141 void NotificationViewTest::TearDown() {
142   widget()->Close();
143   notification_view_.reset();
144   views::ViewsTestBase::TearDown();
145 }
146
147 void NotificationViewTest::ClickOnNotification(
148     const std::string& notification_id) {
149   // For this test, this method should not be invoked.
150   NOTREACHED();
151 }
152
153 void NotificationViewTest::RemoveNotification(
154     const std::string& notification_id,
155     bool by_user) {
156   // For this test, this method should not be invoked.
157   NOTREACHED();
158 }
159
160 scoped_ptr<ui::MenuModel> NotificationViewTest::CreateMenuModel(
161     const NotifierId& notifier_id,
162     const base::string16& display_source) {
163   // For this test, this method should not be invoked.
164   NOTREACHED();
165   return scoped_ptr<ui::MenuModel>();
166 }
167
168 bool NotificationViewTest::HasClickedListener(
169     const std::string& notification_id) {
170   return true;
171 }
172
173 void NotificationViewTest::ClickOnNotificationButton(
174     const std::string& notification_id,
175     int button_index) {
176   // For this test, this method should not be invoked.
177   NOTREACHED();
178 }
179
180 /* Unit tests *****************************************************************/
181
182 TEST_F(NotificationViewTest, CreateOrUpdateTest) {
183   EXPECT_TRUE(NULL != notification_view()->title_view_);
184   EXPECT_TRUE(NULL != notification_view()->message_view_);
185   EXPECT_TRUE(NULL != notification_view()->icon_view_);
186   EXPECT_TRUE(NULL != notification_view()->image_view_);
187
188   notification()->set_image(gfx::Image());
189   notification()->set_title(base::ASCIIToUTF16(""));
190   notification()->set_message(base::ASCIIToUTF16(""));
191   notification()->set_icon(gfx::Image());
192
193   notification_view()->CreateOrUpdateViews(*notification());
194   EXPECT_TRUE(NULL == notification_view()->title_view_);
195   EXPECT_TRUE(NULL == notification_view()->message_view_);
196   EXPECT_TRUE(NULL == notification_view()->image_view_);
197   // We still expect an icon view for all layouts.
198   EXPECT_TRUE(NULL != notification_view()->icon_view_);
199 }
200
201 TEST_F(NotificationViewTest, TestLineLimits) {
202   notification()->set_image(CreateTestImage(0, 0));
203   notification()->set_context_message(base::ASCIIToUTF16(""));
204   notification_view()->CreateOrUpdateViews(*notification());
205
206   EXPECT_EQ(5, notification_view()->GetMessageLineLimit(0, 360));
207   EXPECT_EQ(5, notification_view()->GetMessageLineLimit(1, 360));
208   EXPECT_EQ(3, notification_view()->GetMessageLineLimit(2, 360));
209
210   notification()->set_image(CreateTestImage(2, 2));
211   notification_view()->CreateOrUpdateViews(*notification());
212
213   EXPECT_EQ(2, notification_view()->GetMessageLineLimit(0, 360));
214   EXPECT_EQ(2, notification_view()->GetMessageLineLimit(1, 360));
215   EXPECT_EQ(1, notification_view()->GetMessageLineLimit(2, 360));
216
217   notification()->set_context_message(base::UTF8ToUTF16("foo"));
218   notification_view()->CreateOrUpdateViews(*notification());
219
220   EXPECT_TRUE(notification_view()->context_message_view_ != NULL);
221
222   EXPECT_EQ(1, notification_view()->GetMessageLineLimit(0, 360));
223   EXPECT_EQ(1, notification_view()->GetMessageLineLimit(1, 360));
224   EXPECT_EQ(0, notification_view()->GetMessageLineLimit(2, 360));
225 }
226
227 TEST_F(NotificationViewTest, UpdateButtonsStateTest) {
228   notification()->set_buttons(CreateButtons(2));
229   notification_view()->CreateOrUpdateViews(*notification());
230   widget()->Show();
231
232   EXPECT_EQ(views::CustomButton::STATE_NORMAL,
233             notification_view()->action_buttons_[0]->state());
234
235   // Now construct a mouse move event 1 pixel inside the boundary of the action
236   // button.
237   gfx::Point cursor_location(1, 1);
238   views::View::ConvertPointToWidget(notification_view()->action_buttons_[0],
239                                     &cursor_location);
240   ui::MouseEvent move(ui::ET_MOUSE_MOVED,
241                       cursor_location,
242                       cursor_location,
243                       ui::EF_NONE,
244                       ui::EF_NONE);
245   widget()->OnMouseEvent(&move);
246
247   EXPECT_EQ(views::CustomButton::STATE_HOVERED,
248             notification_view()->action_buttons_[0]->state());
249
250   notification_view()->CreateOrUpdateViews(*notification());
251
252   EXPECT_EQ(views::CustomButton::STATE_HOVERED,
253             notification_view()->action_buttons_[0]->state());
254
255   // Now construct a mouse move event 1 pixel outside the boundary of the
256   // widget.
257   cursor_location = gfx::Point(-1, -1);
258   move = ui::MouseEvent(ui::ET_MOUSE_MOVED,
259                         cursor_location,
260                         cursor_location,
261                         ui::EF_NONE,
262                         ui::EF_NONE);
263   widget()->OnMouseEvent(&move);
264
265   EXPECT_EQ(views::CustomButton::STATE_NORMAL,
266             notification_view()->action_buttons_[0]->state());
267 }
268
269 TEST_F(NotificationViewTest, UpdateButtonCountTest) {
270   notification()->set_buttons(CreateButtons(2));
271   notification_view()->CreateOrUpdateViews(*notification());
272   widget()->Show();
273
274   EXPECT_EQ(views::CustomButton::STATE_NORMAL,
275             notification_view()->action_buttons_[0]->state());
276   EXPECT_EQ(views::CustomButton::STATE_NORMAL,
277             notification_view()->action_buttons_[1]->state());
278
279   // Now construct a mouse move event 1 pixel inside the boundary of the action
280   // button.
281   gfx::Point cursor_location(1, 1);
282   views::View::ConvertPointToWidget(notification_view()->action_buttons_[0],
283                                     &cursor_location);
284   ui::MouseEvent move(ui::ET_MOUSE_MOVED,
285                       cursor_location,
286                       cursor_location,
287                       ui::EF_NONE,
288                       ui::EF_NONE);
289   widget()->OnMouseEvent(&move);
290
291   EXPECT_EQ(views::CustomButton::STATE_HOVERED,
292             notification_view()->action_buttons_[0]->state());
293   EXPECT_EQ(views::CustomButton::STATE_NORMAL,
294             notification_view()->action_buttons_[1]->state());
295
296   notification()->set_buttons(CreateButtons(1));
297   notification_view()->CreateOrUpdateViews(*notification());
298
299   EXPECT_EQ(views::CustomButton::STATE_HOVERED,
300             notification_view()->action_buttons_[0]->state());
301   EXPECT_EQ(1u, notification_view()->action_buttons_.size());
302
303   // Now construct a mouse move event 1 pixel outside the boundary of the
304   // widget.
305   cursor_location = gfx::Point(-1, -1);
306   move = ui::MouseEvent(ui::ET_MOUSE_MOVED,
307                         cursor_location,
308                         cursor_location,
309                         ui::EF_NONE,
310                         ui::EF_NONE);
311   widget()->OnMouseEvent(&move);
312
313   EXPECT_EQ(views::CustomButton::STATE_NORMAL,
314             notification_view()->action_buttons_[0]->state());
315 }
316
317 TEST_F(NotificationViewTest, ViewOrderingTest) {
318   // Tests that views are created in the correct vertical order.
319   notification()->set_buttons(CreateButtons(2));
320
321   // Layout the initial views.
322   UpdateNotificationViews();
323
324   // Double-check that vertical order is correct.
325   CheckVerticalOrderInNotification();
326
327   // Tests that views remain in that order even after an update.
328   UpdateNotificationViews();
329   CheckVerticalOrderInNotification();
330 }
331
332 }  // namespace message_center