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