Pin Chrome's shortcut to the Win10 Start menu on install and OS upgrade.
[chromium-blink-merge.git] / ui / views / bubble / bubble_delegate_unittest.cc
blobec5ab14429041e07f1be881f84e456b9d9645894
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.
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"
13 namespace views {
15 namespace {
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_);
25 ~TestBubbleDelegateView() override {}
27 void SetAnchorRectForTest(gfx::Rect rect) {
28 SetAnchorRect(rect);
31 void SetAnchorViewForTest(View* view) {
32 SetAnchorView(view);
35 // BubbleDelegateView overrides:
36 View* GetInitiallyFocusedView() override { return view_; }
37 gfx::Size GetPreferredSize() const override { return gfx::Size(200, 200); }
39 private:
40 View* view_;
42 DISALLOW_COPY_AND_ASSIGN(TestBubbleDelegateView);
45 class BubbleDelegateTest : public ViewsTestBase {
46 public:
47 BubbleDelegateTest() {}
48 ~BubbleDelegateTest() override {}
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;
59 private:
60 DISALLOW_COPY_AND_ASSIGN(BubbleDelegateTest);
63 } // namespace
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();
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());
80 EXPECT_FALSE(bubble_observer.widget_closed());
81 bubble_widget->CloseNow();
82 EXPECT_TRUE(bubble_observer.widget_closed());
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());
98 bubble_widget->Show();
99 EXPECT_EQ(anchor_widget, bubble_delegate->anchor_widget());
100 EXPECT_FALSE(bubble_observer.widget_closed());
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());
107 // Ensure that closing the anchor widget also closes the bubble itself.
108 anchor_widget->CloseNow();
109 EXPECT_TRUE(bubble_observer.widget_closed());
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);
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());
135 // Create the bubble.
136 bubble_widget->Show();
137 EXPECT_EQ(anchor_widget, bubble_delegate->anchor_widget());
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());
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);
155 anchor_widget->GetContentsView()->SetBounds(10, 10, 100, 100);
156 const gfx::Rect view_rect = bubble_delegate->GetAnchorRect();
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());
163 TEST_F(BubbleDelegateTest, ResetAnchorWidget) {
164 scoped_ptr<Widget> anchor_widget(CreateTestWidget());
165 BubbleDelegateView* bubble_delegate = new BubbleDelegateView(
166 anchor_widget->GetContentsView(), BubbleBorder::NONE);
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());
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());
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());
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());
198 // Ensure that closing the parent widget also closes the bubble itself.
199 parent_widget->CloseNow();
200 EXPECT_TRUE(bubble_observer.widget_closed());
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();
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();
221 struct {
222 const int point;
223 const int hit;
224 } cases[] = {
225 { border, HTNOWHERE },
226 { border + 50, HTCLIENT },
227 { 1000, HTNOWHERE },
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;
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());
245 anchor_widget->Show();
246 bubble_widget->Show();
247 EXPECT_TRUE(bubble_widget->IsVisible());
248 anchor_widget->SetBounds(gfx::Rect(10, 10, 100, 100));
249 EXPECT_TRUE(bubble_widget->IsVisible());
252 // Test that setting WidgetDelegate::set_can_activate() to false makes the
253 // widget created via BubbleDelegateView::CreateBubble() not activatable.
254 TEST_F(BubbleDelegateTest, NotActivatable) {
255 scoped_ptr<Widget> anchor_widget(CreateTestWidget());
256 BubbleDelegateView* bubble_delegate = new BubbleDelegateView(
257 anchor_widget->GetContentsView(), BubbleBorder::NONE);
258 bubble_delegate->set_can_activate(false);
259 Widget* bubble_widget = BubbleDelegateView::CreateBubble(bubble_delegate);
260 bubble_widget->Show();
261 EXPECT_FALSE(bubble_widget->CanActivate());
264 } // namespace views