Pin Chrome's shortcut to the Win10 Start menu on install and OS upgrade.
[chromium-blink-merge.git] / ui / views / bubble / bubble_frame_view_unittest.cc
blobd3575a666376a20552c36fbb462e7a36615d9385
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 "base/memory/scoped_ptr.h"
6 #include "ui/gfx/geometry/insets.h"
7 #include "ui/gfx/geometry/rect.h"
8 #include "ui/gfx/geometry/size.h"
9 #include "ui/views/bubble/bubble_border.h"
10 #include "ui/views/bubble/bubble_frame_view.h"
11 #include "ui/views/test/test_views.h"
12 #include "ui/views/test/views_test_base.h"
13 #include "ui/views/widget/widget.h"
14 #include "ui/views/widget/widget_delegate.h"
16 namespace views {
18 typedef ViewsTestBase BubbleFrameViewTest;
20 namespace {
22 const BubbleBorder::Arrow kArrow = BubbleBorder::TOP_LEFT;
23 const SkColor kColor = SK_ColorRED;
24 const int kMargin = 6;
25 const int kMinimumClientWidth = 100;
26 const int kMinimumClientHeight = 200;
27 const int kMaximumClientWidth = 300;
28 const int kMaximumClientHeight = 300;
29 const int kPreferredClientWidth = 150;
30 const int kPreferredClientHeight = 250;
31 const int kExpectedBorderWidth = 22;
32 const int kExpectedBorderHeight = 29;
34 class TestBubbleFrameViewWidgetDelegate : public WidgetDelegate {
35 public:
36 TestBubbleFrameViewWidgetDelegate(Widget* widget) : widget_(widget) {}
38 ~TestBubbleFrameViewWidgetDelegate() override {}
40 // WidgetDelegate overrides:
41 Widget* GetWidget() override { return widget_; }
42 const Widget* GetWidget() const override { return widget_; }
44 View* GetContentsView() override {
45 if (!contents_view_) {
46 StaticSizedView* contents_view = new StaticSizedView(
47 gfx::Size(kPreferredClientWidth, kPreferredClientHeight));
48 contents_view->set_minimum_size(
49 gfx::Size(kMinimumClientWidth, kMinimumClientHeight));
50 contents_view->set_maximum_size(
51 gfx::Size(kMaximumClientWidth, kMaximumClientHeight));
52 contents_view_ = contents_view;
54 return contents_view_;
57 private:
58 Widget* widget_;
59 View* contents_view_ = nullptr; // Owned by |widget_|.
62 class TestBubbleFrameView : public BubbleFrameView {
63 public:
64 TestBubbleFrameView(ViewsTestBase* test_base)
65 : BubbleFrameView(gfx::Insets(kMargin, kMargin, kMargin, kMargin)),
66 test_base_(test_base),
67 available_bounds_(gfx::Rect(0, 0, 1000, 1000)) {
68 SetBubbleBorder(scoped_ptr<BubbleBorder>(
69 new BubbleBorder(kArrow, BubbleBorder::NO_SHADOW, kColor)));
71 ~TestBubbleFrameView() override {}
73 // View overrides:
74 const Widget* GetWidget() const override {
75 if (!widget_) {
76 widget_.reset(new Widget);
77 widget_delegate_.reset(
78 new TestBubbleFrameViewWidgetDelegate(widget_.get()));
79 Widget::InitParams params =
80 test_base_->CreateParams(Widget::InitParams::TYPE_BUBBLE);
81 params.delegate = widget_delegate_.get();
82 params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
83 widget_->Init(params);
86 return widget_.get();
89 // BubbleFrameView overrides:
90 gfx::Rect GetAvailableScreenBounds(const gfx::Rect& rect) override {
91 return available_bounds_;
94 private:
95 ViewsTestBase* test_base_;
97 gfx::Rect available_bounds_;
99 // Widget returned by GetWidget(). Only created if GetWidget() is called.
100 mutable scoped_ptr<TestBubbleFrameViewWidgetDelegate> widget_delegate_;
101 mutable scoped_ptr<Widget> widget_;
103 DISALLOW_COPY_AND_ASSIGN(TestBubbleFrameView);
106 } // namespace
108 TEST_F(BubbleFrameViewTest, GetBoundsForClientView) {
109 TestBubbleFrameView frame(this);
110 EXPECT_EQ(kArrow, frame.bubble_border()->arrow());
111 EXPECT_EQ(kColor, frame.bubble_border()->background_color());
113 int margin_x = frame.content_margins().left();
114 int margin_y = frame.content_margins().top();
115 gfx::Insets insets = frame.bubble_border()->GetInsets();
116 EXPECT_EQ(insets.left() + margin_x, frame.GetBoundsForClientView().x());
117 EXPECT_EQ(insets.top() + margin_y, frame.GetBoundsForClientView().y());
120 // Tests that the arrow is mirrored as needed to better fit the screen.
121 TEST_F(BubbleFrameViewTest, GetUpdatedWindowBounds) {
122 TestBubbleFrameView frame(this);
123 gfx::Rect window_bounds;
125 gfx::Insets insets = frame.bubble_border()->GetInsets();
126 int xposition = 95 - insets.width();
128 // Test that the info bubble displays normally when it fits.
129 frame.bubble_border()->set_arrow(BubbleBorder::TOP_LEFT);
130 window_bounds = frame.GetUpdatedWindowBounds(
131 gfx::Rect(100, 100, 50, 50), // |anchor_rect|
132 gfx::Size(500, 500), // |client_size|
133 true); // |adjust_if_offscreen|
134 EXPECT_EQ(BubbleBorder::TOP_LEFT, frame.bubble_border()->arrow());
135 EXPECT_GT(window_bounds.x(), xposition);
136 EXPECT_GT(window_bounds.y(), 100 + 50 - 10); // -10 to roughly compensate for
137 // arrow overlap.
139 // Test bubble not fitting on left.
140 frame.bubble_border()->set_arrow(BubbleBorder::TOP_RIGHT);
141 window_bounds = frame.GetUpdatedWindowBounds(
142 gfx::Rect(100, 100, 50, 50), // |anchor_rect|
143 gfx::Size(500, 500), // |client_size|
144 true); // |adjust_if_offscreen|
145 EXPECT_EQ(BubbleBorder::TOP_LEFT, frame.bubble_border()->arrow());
146 EXPECT_GT(window_bounds.x(), xposition);
147 EXPECT_GT(window_bounds.y(), 100 + 50 - 10); // -10 to roughly compensate for
148 // arrow overlap.
150 // Test bubble not fitting on left or top.
151 frame.bubble_border()->set_arrow(BubbleBorder::BOTTOM_RIGHT);
152 window_bounds = frame.GetUpdatedWindowBounds(
153 gfx::Rect(100, 100, 50, 50), // |anchor_rect|
154 gfx::Size(500, 500), // |client_size|
155 true); // |adjust_if_offscreen|
156 EXPECT_EQ(BubbleBorder::TOP_LEFT, frame.bubble_border()->arrow());
157 EXPECT_GT(window_bounds.x(), xposition);
158 EXPECT_GT(window_bounds.y(), 100 + 50 - 10); // -10 to roughly compensate for
159 // arrow overlap.
161 // Test bubble not fitting on top.
162 frame.bubble_border()->set_arrow(BubbleBorder::BOTTOM_LEFT);
163 window_bounds = frame.GetUpdatedWindowBounds(
164 gfx::Rect(100, 100, 50, 50), // |anchor_rect|
165 gfx::Size(500, 500), // |client_size|
166 true); // |adjust_if_offscreen|
167 EXPECT_EQ(BubbleBorder::TOP_LEFT, frame.bubble_border()->arrow());
168 EXPECT_GT(window_bounds.x(), xposition);
169 EXPECT_GT(window_bounds.y(), 100 + 50 - 10); // -10 to roughly compensate for
170 // arrow overlap.
172 // Test bubble not fitting on top and right.
173 frame.bubble_border()->set_arrow(BubbleBorder::BOTTOM_LEFT);
174 window_bounds = frame.GetUpdatedWindowBounds(
175 gfx::Rect(900, 100, 50, 50), // |anchor_rect|
176 gfx::Size(500, 500), // |client_size|
177 true); // |adjust_if_offscreen|
178 EXPECT_EQ(BubbleBorder::TOP_RIGHT, frame.bubble_border()->arrow());
179 EXPECT_LT(window_bounds.x(), 900 + 50 - 500);
180 EXPECT_GT(window_bounds.y(), 100 + 50 - 10); // -10 to roughly compensate for
181 // arrow overlap.
183 // Test bubble not fitting on right.
184 frame.bubble_border()->set_arrow(BubbleBorder::TOP_LEFT);
185 window_bounds = frame.GetUpdatedWindowBounds(
186 gfx::Rect(900, 100, 50, 50), // |anchor_rect|
187 gfx::Size(500, 500), // |client_size|
188 true); // |adjust_if_offscreen|
189 EXPECT_EQ(BubbleBorder::TOP_RIGHT, frame.bubble_border()->arrow());
190 EXPECT_LT(window_bounds.x(), 900 + 50 - 500);
191 EXPECT_GT(window_bounds.y(), 100 + 50 - 10); // -10 to roughly compensate for
192 // arrow overlap.
194 // Test bubble not fitting on bottom and right.
195 frame.bubble_border()->set_arrow(BubbleBorder::TOP_LEFT);
196 window_bounds = frame.GetUpdatedWindowBounds(
197 gfx::Rect(900, 900, 50, 50), // |anchor_rect|
198 gfx::Size(500, 500), // |client_size|
199 true); // |adjust_if_offscreen|
200 EXPECT_EQ(BubbleBorder::BOTTOM_RIGHT, frame.bubble_border()->arrow());
201 EXPECT_LT(window_bounds.x(), 900 + 50 - 500);
202 EXPECT_LT(window_bounds.y(), 900 - 500 - 15); // -15 to roughly compensate
203 // for arrow height.
205 // Test bubble not fitting at the bottom.
206 frame.bubble_border()->set_arrow(BubbleBorder::TOP_LEFT);
207 window_bounds = frame.GetUpdatedWindowBounds(
208 gfx::Rect(100, 900, 50, 50), // |anchor_rect|
209 gfx::Size(500, 500), // |client_size|
210 true); // |adjust_if_offscreen|
211 EXPECT_EQ(BubbleBorder::BOTTOM_LEFT, frame.bubble_border()->arrow());
212 // The window should be right aligned with the anchor_rect.
213 EXPECT_LT(window_bounds.x(), 900 + 50 - 500);
214 EXPECT_LT(window_bounds.y(), 900 - 500 - 15); // -15 to roughly compensate
215 // for arrow height.
217 // Test bubble not fitting at the bottom and left.
218 frame.bubble_border()->set_arrow(BubbleBorder::TOP_RIGHT);
219 window_bounds = frame.GetUpdatedWindowBounds(
220 gfx::Rect(100, 900, 50, 50), // |anchor_rect|
221 gfx::Size(500, 500), // |client_size|
222 true); // |adjust_if_offscreen|
223 EXPECT_EQ(BubbleBorder::BOTTOM_LEFT, frame.bubble_border()->arrow());
224 // The window should be right aligned with the anchor_rect.
225 EXPECT_LT(window_bounds.x(), 900 + 50 - 500);
226 EXPECT_LT(window_bounds.y(), 900 - 500 - 15); // -15 to roughly compensate
227 // for arrow height.
230 // Tests that the arrow is not moved when the info-bubble does not fit the
231 // screen but moving it would make matter worse.
232 TEST_F(BubbleFrameViewTest, GetUpdatedWindowBoundsMirroringFails) {
233 TestBubbleFrameView frame(this);
234 frame.bubble_border()->set_arrow(BubbleBorder::TOP_LEFT);
235 gfx::Rect window_bounds = frame.GetUpdatedWindowBounds(
236 gfx::Rect(400, 100, 50, 50), // |anchor_rect|
237 gfx::Size(500, 700), // |client_size|
238 true); // |adjust_if_offscreen|
239 EXPECT_EQ(BubbleBorder::TOP_LEFT, frame.bubble_border()->arrow());
242 TEST_F(BubbleFrameViewTest, TestMirroringForCenteredArrow) {
243 TestBubbleFrameView frame(this);
245 // Test bubble not fitting above the anchor.
246 frame.bubble_border()->set_arrow(BubbleBorder::BOTTOM_CENTER);
247 gfx::Rect window_bounds = frame.GetUpdatedWindowBounds(
248 gfx::Rect(100, 100, 50, 50), // |anchor_rect|
249 gfx::Size(500, 700), // |client_size|
250 true); // |adjust_if_offscreen|
251 EXPECT_EQ(BubbleBorder::TOP_CENTER, frame.bubble_border()->arrow());
253 // Test bubble not fitting below the anchor.
254 frame.bubble_border()->set_arrow(BubbleBorder::TOP_CENTER);
255 window_bounds = frame.GetUpdatedWindowBounds(
256 gfx::Rect(300, 800, 50, 50), // |anchor_rect|
257 gfx::Size(500, 200), // |client_size|
258 true); // |adjust_if_offscreen|
259 EXPECT_EQ(BubbleBorder::BOTTOM_CENTER, frame.bubble_border()->arrow());
261 // Test bubble not fitting to the right of the anchor.
262 frame.bubble_border()->set_arrow(BubbleBorder::LEFT_CENTER);
263 window_bounds = frame.GetUpdatedWindowBounds(
264 gfx::Rect(800, 300, 50, 50), // |anchor_rect|
265 gfx::Size(200, 500), // |client_size|
266 true); // |adjust_if_offscreen|
267 EXPECT_EQ(BubbleBorder::RIGHT_CENTER, frame.bubble_border()->arrow());
269 // Test bubble not fitting to the left of the anchor.
270 frame.bubble_border()->set_arrow(BubbleBorder::RIGHT_CENTER);
271 window_bounds = frame.GetUpdatedWindowBounds(
272 gfx::Rect(100, 300, 50, 50), // |anchor_rect|
273 gfx::Size(500, 500), // |client_size|
274 true); // |adjust_if_offscreen|
275 EXPECT_EQ(BubbleBorder::LEFT_CENTER, frame.bubble_border()->arrow());
278 // Test that the arrow will not be mirrored when |adjust_if_offscreen| is false.
279 TEST_F(BubbleFrameViewTest, GetUpdatedWindowBoundsDontTryMirror) {
280 TestBubbleFrameView frame(this);
281 frame.bubble_border()->set_arrow(BubbleBorder::TOP_RIGHT);
282 gfx::Rect window_bounds = frame.GetUpdatedWindowBounds(
283 gfx::Rect(100, 900, 50, 50), // |anchor_rect|
284 gfx::Size(500, 500), // |client_size|
285 false); // |adjust_if_offscreen|
286 EXPECT_EQ(BubbleBorder::TOP_RIGHT, frame.bubble_border()->arrow());
287 // The coordinates should be pointing to anchor_rect from TOP_RIGHT.
288 EXPECT_LT(window_bounds.x(), 100 + 50 - 500);
289 EXPECT_GT(window_bounds.y(), 900 + 50 - 10); // -10 to roughly compensate for
290 // arrow overlap.
293 // Test that the center arrow is moved as needed to fit the screen.
294 TEST_F(BubbleFrameViewTest, GetUpdatedWindowBoundsCenterArrows) {
295 TestBubbleFrameView frame(this);
296 gfx::Rect window_bounds;
298 // Test that the bubble displays normally when it fits.
299 frame.bubble_border()->set_arrow(BubbleBorder::TOP_CENTER);
300 window_bounds = frame.GetUpdatedWindowBounds(
301 gfx::Rect(500, 100, 50, 50), // |anchor_rect|
302 gfx::Size(500, 500), // |client_size|
303 true); // |adjust_if_offscreen|
304 EXPECT_EQ(BubbleBorder::TOP_CENTER, frame.bubble_border()->arrow());
305 EXPECT_EQ(window_bounds.x() + window_bounds.width() / 2, 525);
307 frame.bubble_border()->set_arrow(BubbleBorder::BOTTOM_CENTER);
308 window_bounds = frame.GetUpdatedWindowBounds(
309 gfx::Rect(500, 900, 50, 50), // |anchor_rect|
310 gfx::Size(500, 500), // |client_size|
311 true); // |adjust_if_offscreen|
312 EXPECT_EQ(BubbleBorder::BOTTOM_CENTER, frame.bubble_border()->arrow());
313 EXPECT_EQ(window_bounds.x() + window_bounds.width() / 2, 525);
315 frame.bubble_border()->set_arrow(BubbleBorder::LEFT_CENTER);
316 window_bounds = frame.GetUpdatedWindowBounds(
317 gfx::Rect(100, 400, 50, 50), // |anchor_rect|
318 gfx::Size(500, 500), // |client_size|
319 true); // |adjust_if_offscreen|
320 EXPECT_EQ(BubbleBorder::LEFT_CENTER, frame.bubble_border()->arrow());
321 EXPECT_EQ(window_bounds.y() + window_bounds.height() / 2, 425);
323 frame.bubble_border()->set_arrow(BubbleBorder::RIGHT_CENTER);
324 window_bounds = frame.GetUpdatedWindowBounds(
325 gfx::Rect(900, 400, 50, 50), // |anchor_rect|
326 gfx::Size(500, 500), // |client_size|
327 true); // |adjust_if_offscreen|
328 EXPECT_EQ(BubbleBorder::RIGHT_CENTER, frame.bubble_border()->arrow());
329 EXPECT_EQ(window_bounds.y() + window_bounds.height() / 2, 425);
331 // Test bubble not fitting left screen edge.
332 frame.bubble_border()->set_arrow(BubbleBorder::TOP_CENTER);
333 window_bounds = frame.GetUpdatedWindowBounds(
334 gfx::Rect(100, 100, 50, 50), // |anchor_rect|
335 gfx::Size(500, 500), // |client_size|
336 true); // |adjust_if_offscreen|
337 EXPECT_EQ(BubbleBorder::TOP_CENTER, frame.bubble_border()->arrow());
338 EXPECT_EQ(window_bounds.x(), 0);
339 EXPECT_EQ(window_bounds.x() +
340 frame.bubble_border()->GetArrowOffset(window_bounds.size()), 125);
342 frame.bubble_border()->set_arrow(BubbleBorder::BOTTOM_CENTER);
343 window_bounds = frame.GetUpdatedWindowBounds(
344 gfx::Rect(100, 900, 50, 50), // |anchor_rect|
345 gfx::Size(500, 500), // |client_size|
346 true); // |adjust_if_offscreen|
347 EXPECT_EQ(BubbleBorder::BOTTOM_CENTER, frame.bubble_border()->arrow());
348 EXPECT_EQ(window_bounds.x(), 0);
349 EXPECT_EQ(window_bounds.x() +
350 frame.bubble_border()->GetArrowOffset(window_bounds.size()), 125);
352 // Test bubble not fitting right screen edge.
353 frame.bubble_border()->set_arrow(BubbleBorder::TOP_CENTER);
354 window_bounds = frame.GetUpdatedWindowBounds(
355 gfx::Rect(900, 100, 50, 50), // |anchor_rect|
356 gfx::Size(500, 500), // |client_size|
357 true); // |adjust_if_offscreen|
358 EXPECT_EQ(BubbleBorder::TOP_CENTER, frame.bubble_border()->arrow());
359 EXPECT_EQ(window_bounds.right(), 1000);
360 EXPECT_EQ(window_bounds.x() +
361 frame.bubble_border()->GetArrowOffset(window_bounds.size()), 925);
363 frame.bubble_border()->set_arrow(BubbleBorder::BOTTOM_CENTER);
364 window_bounds = frame.GetUpdatedWindowBounds(
365 gfx::Rect(900, 900, 50, 50), // |anchor_rect|
366 gfx::Size(500, 500), // |client_size|
367 true); // |adjust_if_offscreen|
368 EXPECT_EQ(BubbleBorder::BOTTOM_CENTER, frame.bubble_border()->arrow());
369 EXPECT_EQ(window_bounds.right(), 1000);
370 EXPECT_EQ(window_bounds.x() +
371 frame.bubble_border()->GetArrowOffset(window_bounds.size()), 925);
373 // Test bubble not fitting top screen edge.
374 frame.bubble_border()->set_arrow(BubbleBorder::LEFT_CENTER);
375 window_bounds = frame.GetUpdatedWindowBounds(
376 gfx::Rect(100, 100, 50, 50), // |anchor_rect|
377 gfx::Size(500, 500), // |client_size|
378 true); // |adjust_if_offscreen|
379 EXPECT_EQ(BubbleBorder::LEFT_CENTER, frame.bubble_border()->arrow());
380 EXPECT_EQ(window_bounds.y(), 0);
381 EXPECT_EQ(window_bounds.y() +
382 frame.bubble_border()->GetArrowOffset(window_bounds.size()), 125);
384 frame.bubble_border()->set_arrow(BubbleBorder::RIGHT_CENTER);
385 window_bounds = frame.GetUpdatedWindowBounds(
386 gfx::Rect(900, 100, 50, 50), // |anchor_rect|
387 gfx::Size(500, 500), // |client_size|
388 true); // |adjust_if_offscreen|
389 EXPECT_EQ(BubbleBorder::RIGHT_CENTER, frame.bubble_border()->arrow());
390 EXPECT_EQ(window_bounds.y(), 0);
391 EXPECT_EQ(window_bounds.y() +
392 frame.bubble_border()->GetArrowOffset(window_bounds.size()), 125);
394 // Test bubble not fitting bottom screen edge.
395 frame.bubble_border()->set_arrow(BubbleBorder::LEFT_CENTER);
396 window_bounds = frame.GetUpdatedWindowBounds(
397 gfx::Rect(100, 900, 50, 50), // |anchor_rect|
398 gfx::Size(500, 500), // |client_size|
399 true); // |adjust_if_offscreen|
400 EXPECT_EQ(BubbleBorder::LEFT_CENTER, frame.bubble_border()->arrow());
401 EXPECT_EQ(window_bounds.bottom(), 1000);
402 EXPECT_EQ(window_bounds.y() +
403 frame.bubble_border()->GetArrowOffset(window_bounds.size()), 925);
405 frame.bubble_border()->set_arrow(BubbleBorder::RIGHT_CENTER);
406 window_bounds = frame.GetUpdatedWindowBounds(
407 gfx::Rect(900, 900, 50, 50), // |anchor_rect|
408 gfx::Size(500, 500), // |client_size|
409 true); // |adjust_if_offscreen|
410 EXPECT_EQ(BubbleBorder::RIGHT_CENTER, frame.bubble_border()->arrow());
411 EXPECT_EQ(window_bounds.bottom(), 1000);
412 EXPECT_EQ(window_bounds.y() +
413 frame.bubble_border()->GetArrowOffset(window_bounds.size()), 925);
416 TEST_F(BubbleFrameViewTest, GetPreferredSize) {
417 TestBubbleFrameView frame(this);
418 gfx::Size preferred_size = frame.GetPreferredSize();
419 // Expect that a border has been added to the preferred size.
420 EXPECT_EQ(kPreferredClientWidth + kExpectedBorderWidth,
421 preferred_size.width());
422 EXPECT_EQ(kPreferredClientHeight + kExpectedBorderHeight,
423 preferred_size.height());
426 TEST_F(BubbleFrameViewTest, GetMinimumSize) {
427 TestBubbleFrameView frame(this);
428 gfx::Size minimum_size = frame.GetMinimumSize();
429 // Expect that a border has been added to the minimum size.
430 EXPECT_EQ(kMinimumClientWidth + kExpectedBorderWidth, minimum_size.width());
431 EXPECT_EQ(kMinimumClientHeight + kExpectedBorderHeight,
432 minimum_size.height());
435 TEST_F(BubbleFrameViewTest, GetMaximumSize) {
436 TestBubbleFrameView frame(this);
437 gfx::Size maximum_size = frame.GetMaximumSize();
438 #if defined(OS_WIN)
439 // On Windows, GetMaximumSize causes problems with DWM, so it should just be 0
440 // (unlimited). See http://crbug.com/506206.
441 EXPECT_EQ(0, maximum_size.width());
442 EXPECT_EQ(0, maximum_size.height());
443 #else
444 // Should ignore the contents view's maximum size and use the preferred size.
445 EXPECT_EQ(kPreferredClientWidth + kExpectedBorderWidth, maximum_size.width());
446 EXPECT_EQ(kPreferredClientHeight + kExpectedBorderHeight,
447 maximum_size.height());
448 #endif
451 } // namespace views