782c9e79d30ef6f495a06cdf1c8b30c7f03badbd
[platform/framework/web/crosswalk.git] / src / ui / views / bubble / bubble_delegate_unittest.cc
1 // Copyright (c) 2012 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/base/hit_test.h"
6 #include "ui/views/bubble/bubble_delegate.h"
7 #include "ui/views/bubble/bubble_frame_view.h"
8 #include "ui/views/test/test_widget_observer.h"
9 #include "ui/views/test/views_test_base.h"
10 #include "ui/views/widget/widget.h"
11 #include "ui/views/widget/widget_observer.h"
12
13 namespace views {
14
15 namespace {
16
17 class TestBubbleDelegateView : public BubbleDelegateView {
18  public:
19   TestBubbleDelegateView(View* anchor_view)
20       : BubbleDelegateView(anchor_view, BubbleBorder::TOP_LEFT),
21         view_(new View()) {
22     view_->SetFocusable(true);
23     AddChildView(view_);
24   }
25   ~TestBubbleDelegateView() override {}
26
27   void SetAnchorRectForTest(gfx::Rect rect) {
28     SetAnchorRect(rect);
29   }
30
31   void SetAnchorViewForTest(View* view) {
32     SetAnchorView(view);
33   }
34
35   // BubbleDelegateView overrides:
36   View* GetInitiallyFocusedView() override { return view_; }
37   gfx::Size GetPreferredSize() const override { return gfx::Size(200, 200); }
38
39  private:
40   View* view_;
41
42   DISALLOW_COPY_AND_ASSIGN(TestBubbleDelegateView);
43 };
44
45 class BubbleDelegateTest : public ViewsTestBase {
46  public:
47   BubbleDelegateTest() {}
48   ~BubbleDelegateTest() override {}
49
50   // Creates a test widget that owns its native widget.
51   Widget* CreateTestWidget() {
52     Widget* widget = new Widget();
53     Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_WINDOW);
54     params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
55     widget->Init(params);
56     return widget;
57   }
58
59  private:
60   DISALLOW_COPY_AND_ASSIGN(BubbleDelegateTest);
61 };
62
63 }  // namespace
64
65 TEST_F(BubbleDelegateTest, CreateDelegate) {
66   scoped_ptr<Widget> anchor_widget(CreateTestWidget());
67   BubbleDelegateView* bubble_delegate = new BubbleDelegateView(
68       anchor_widget->GetContentsView(), BubbleBorder::NONE);
69   bubble_delegate->set_color(SK_ColorGREEN);
70   Widget* bubble_widget = BubbleDelegateView::CreateBubble(bubble_delegate);
71   EXPECT_EQ(bubble_delegate, bubble_widget->widget_delegate());
72   EXPECT_EQ(bubble_widget, bubble_delegate->GetWidget());
73   test::TestWidgetObserver bubble_observer(bubble_widget);
74   bubble_widget->Show();
75
76   BubbleBorder* border = bubble_delegate->GetBubbleFrameView()->bubble_border();
77   EXPECT_EQ(bubble_delegate->arrow(), border->arrow());
78   EXPECT_EQ(bubble_delegate->color(), border->background_color());
79
80   EXPECT_FALSE(bubble_observer.widget_closed());
81   bubble_widget->CloseNow();
82   EXPECT_TRUE(bubble_observer.widget_closed());
83 }
84
85 TEST_F(BubbleDelegateTest, CloseAnchorWidget) {
86   scoped_ptr<Widget> anchor_widget(CreateTestWidget());
87   BubbleDelegateView* bubble_delegate = new BubbleDelegateView(
88       anchor_widget->GetContentsView(), BubbleBorder::NONE);
89   // Preventing close on deactivate should not prevent closing with the anchor.
90   bubble_delegate->set_close_on_deactivate(false);
91   Widget* bubble_widget = BubbleDelegateView::CreateBubble(bubble_delegate);
92   EXPECT_EQ(bubble_delegate, bubble_widget->widget_delegate());
93   EXPECT_EQ(bubble_widget, bubble_delegate->GetWidget());
94   EXPECT_EQ(anchor_widget, bubble_delegate->anchor_widget());
95   test::TestWidgetObserver bubble_observer(bubble_widget);
96   EXPECT_FALSE(bubble_observer.widget_closed());
97
98   bubble_widget->Show();
99   EXPECT_EQ(anchor_widget, bubble_delegate->anchor_widget());
100   EXPECT_FALSE(bubble_observer.widget_closed());
101
102   // TODO(msw): Remove activation hack to prevent bookkeeping errors in:
103   //            aura::test::TestActivationClient::OnWindowDestroyed().
104   scoped_ptr<Widget> smoke_and_mirrors_widget(CreateTestWidget());
105   EXPECT_FALSE(bubble_observer.widget_closed());
106
107   // Ensure that closing the anchor widget also closes the bubble itself.
108   anchor_widget->CloseNow();
109   EXPECT_TRUE(bubble_observer.widget_closed());
110 }
111
112 // This test checks that the bubble delegate is capable to handle an early
113 // destruction of the used anchor view. (Animations and delayed closure of the
114 // bubble will call upon the anchor view to get its location).
115 TEST_F(BubbleDelegateTest, CloseAnchorViewTest) {
116   // Create an anchor widget and add a view to be used as an anchor view.
117   scoped_ptr<Widget> anchor_widget(CreateTestWidget());
118   scoped_ptr<View> anchor_view(new View());
119   anchor_widget->GetContentsView()->AddChildView(anchor_view.get());
120   TestBubbleDelegateView* bubble_delegate = new TestBubbleDelegateView(
121       anchor_view.get());
122   // Prevent flakes by avoiding closing on activation changes.
123   bubble_delegate->set_close_on_deactivate(false);
124   Widget* bubble_widget = BubbleDelegateView::CreateBubble(bubble_delegate);
125
126   // Check that the anchor view is correct and set up an anchor view rect.
127   // Make sure that this rect will get ignored (as long as the anchor view is
128   // attached).
129   EXPECT_EQ(anchor_view, bubble_delegate->GetAnchorView());
130   const gfx::Rect set_anchor_rect = gfx::Rect(10, 10, 100, 100);
131   bubble_delegate->SetAnchorRectForTest(set_anchor_rect);
132   const gfx::Rect view_rect = bubble_delegate->GetAnchorRect();
133   EXPECT_NE(view_rect.ToString(), set_anchor_rect.ToString());
134
135   // Create the bubble.
136   bubble_widget->Show();
137   EXPECT_EQ(anchor_widget, bubble_delegate->anchor_widget());
138
139   // Remove now the anchor view and make sure that the original found rect
140   // is still kept, so that the bubble does not jump when the view gets deleted.
141   anchor_widget->GetContentsView()->RemoveChildView(anchor_view.get());
142   anchor_view.reset();
143   EXPECT_EQ(NULL, bubble_delegate->GetAnchorView());
144   EXPECT_EQ(view_rect.ToString(), bubble_delegate->GetAnchorRect().ToString());
145 }
146
147 // Testing that a move of the anchor view will lead to new bubble locations.
148 TEST_F(BubbleDelegateTest, TestAnchorRectMovesWithViewTest) {
149   // Create an anchor widget and add a view to be used as anchor view.
150   scoped_ptr<Widget> anchor_widget(CreateTestWidget());
151   TestBubbleDelegateView* bubble_delegate = new TestBubbleDelegateView(
152       anchor_widget->GetContentsView());
153   BubbleDelegateView::CreateBubble(bubble_delegate);
154
155   anchor_widget->GetContentsView()->SetBounds(10, 10, 100, 100);
156   const gfx::Rect view_rect = bubble_delegate->GetAnchorRect();
157
158   anchor_widget->GetContentsView()->SetBounds(20, 10, 100, 100);
159   const gfx::Rect view_rect_2 = bubble_delegate->GetAnchorRect();
160   EXPECT_NE(view_rect.ToString(), view_rect_2.ToString());
161 }
162
163 TEST_F(BubbleDelegateTest, ResetAnchorWidget) {
164   scoped_ptr<Widget> anchor_widget(CreateTestWidget());
165   BubbleDelegateView* bubble_delegate = new BubbleDelegateView(
166       anchor_widget->GetContentsView(), BubbleBorder::NONE);
167
168   // Make sure the bubble widget is parented to a widget other than the anchor
169   // widget so that closing the anchor widget does not close the bubble widget.
170   scoped_ptr<Widget> parent_widget(CreateTestWidget());
171   bubble_delegate->set_parent_window(parent_widget->GetNativeView());
172   // Preventing close on deactivate should not prevent closing with the parent.
173   bubble_delegate->set_close_on_deactivate(false);
174   Widget* bubble_widget = BubbleDelegateView::CreateBubble(bubble_delegate);
175   EXPECT_EQ(bubble_delegate, bubble_widget->widget_delegate());
176   EXPECT_EQ(bubble_widget, bubble_delegate->GetWidget());
177   EXPECT_EQ(anchor_widget, bubble_delegate->anchor_widget());
178   test::TestWidgetObserver bubble_observer(bubble_widget);
179   EXPECT_FALSE(bubble_observer.widget_closed());
180
181   // Showing and hiding the bubble widget should have no effect on its anchor.
182   bubble_widget->Show();
183   EXPECT_EQ(anchor_widget, bubble_delegate->anchor_widget());
184   bubble_widget->Hide();
185   EXPECT_EQ(anchor_widget, bubble_delegate->anchor_widget());
186
187   // Ensure that closing the anchor widget clears the bubble's reference to that
188   // anchor widget, but the bubble itself does not close.
189   anchor_widget->CloseNow();
190   EXPECT_NE(anchor_widget, bubble_delegate->anchor_widget());
191   EXPECT_FALSE(bubble_observer.widget_closed());
192
193   // TODO(msw): Remove activation hack to prevent bookkeeping errors in:
194   //            aura::test::TestActivationClient::OnWindowDestroyed().
195   scoped_ptr<Widget> smoke_and_mirrors_widget(CreateTestWidget());
196   EXPECT_FALSE(bubble_observer.widget_closed());
197
198   // Ensure that closing the parent widget also closes the bubble itself.
199   parent_widget->CloseNow();
200   EXPECT_TRUE(bubble_observer.widget_closed());
201 }
202
203 TEST_F(BubbleDelegateTest, InitiallyFocusedView) {
204   scoped_ptr<Widget> anchor_widget(CreateTestWidget());
205   BubbleDelegateView* bubble_delegate = new BubbleDelegateView(
206       anchor_widget->GetContentsView(), BubbleBorder::NONE);
207   Widget* bubble_widget = BubbleDelegateView::CreateBubble(bubble_delegate);
208   EXPECT_EQ(bubble_delegate->GetInitiallyFocusedView(),
209             bubble_widget->GetFocusManager()->GetFocusedView());
210   bubble_widget->CloseNow();
211 }
212
213 TEST_F(BubbleDelegateTest, NonClientHitTest) {
214   scoped_ptr<Widget> anchor_widget(CreateTestWidget());
215   TestBubbleDelegateView* bubble_delegate =
216       new TestBubbleDelegateView(anchor_widget->GetContentsView());
217   BubbleDelegateView::CreateBubble(bubble_delegate);
218   BubbleFrameView* frame = bubble_delegate->GetBubbleFrameView();
219   const int border = frame->bubble_border()->GetBorderThickness();
220
221   struct {
222     const int point;
223     const int hit;
224   } cases[] = {
225     { border,      HTNOWHERE },
226     { border + 50, HTCLIENT  },
227     { 1000,        HTNOWHERE },
228   };
229
230   for (size_t i = 0; i < arraysize(cases); ++i) {
231     gfx::Point point(cases[i].point, cases[i].point);
232     EXPECT_EQ(cases[i].hit, frame->NonClientHitTest(point))
233         << " with border: " << border << ", at point " << cases[i].point;
234   }
235 }
236
237 TEST_F(BubbleDelegateTest, VisibleWhenAnchorWidgetBoundsChanged) {
238   scoped_ptr<Widget> anchor_widget(CreateTestWidget());
239   BubbleDelegateView* bubble_delegate = new BubbleDelegateView(
240       anchor_widget->GetContentsView(), BubbleBorder::NONE);
241   Widget* bubble_widget = BubbleDelegateView::CreateBubble(bubble_delegate);
242   test::TestWidgetObserver bubble_observer(bubble_widget);
243   EXPECT_FALSE(bubble_observer.widget_closed());
244
245   bubble_widget->Show();
246   EXPECT_TRUE(bubble_widget->IsVisible());
247   anchor_widget->SetBounds(gfx::Rect(10, 10, 100, 100));
248   EXPECT_TRUE(bubble_widget->IsVisible());
249 }
250
251 // Test that setting WidgetDelegate::set_can_activate() to false makes the
252 // widget created via BubbleDelegateView::CreateBubble() not activatable.
253 TEST_F(BubbleDelegateTest, NotActivatable) {
254   scoped_ptr<Widget> anchor_widget(CreateTestWidget());
255   BubbleDelegateView* bubble_delegate = new BubbleDelegateView(
256       anchor_widget->GetContentsView(), BubbleBorder::NONE);
257   bubble_delegate->set_can_activate(false);
258   Widget* bubble_widget = BubbleDelegateView::CreateBubble(bubble_delegate);
259   bubble_widget->Show();
260   EXPECT_FALSE(bubble_widget->CanActivate());
261 }
262
263 }  // namespace views