1// Copyright (c) 2011 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 "chrome/browser/ui/views/bubble/border_contents.h"
6#include "testing/gtest/include/gtest/gtest.h"
7
8typedef testing::Test BorderContentsTest;
9
10class TestBorderContents : public BorderContents {
11 public:
12  TestBorderContents() {}
13
14  void set_monitor_bounds(const gfx::Rect& bounds) {
15    monitor_bounds_ = bounds;
16  }
17
18  BubbleBorder* bubble_border() const { return bubble_border_; }
19
20 protected:
21  virtual gfx::Rect GetMonitorBounds(const gfx::Rect& rect) {
22    return monitor_bounds_;
23  }
24
25 private:
26  gfx::Rect monitor_bounds_;
27
28  DISALLOW_COPY_AND_ASSIGN(TestBorderContents);
29};
30
31// Tests that the arrow is moved appropriately when the info-bubble does not fit
32// the screen.
33TEST_F(BorderContentsTest, BorderContentsSizeAndGetBounds) {
34  TestBorderContents border_contents;
35  border_contents.Init();
36
37  // Test that the info bubble displays normally when it fits.
38  gfx::Rect contents_bounds;
39  gfx::Rect window_bounds;
40  border_contents.set_monitor_bounds(gfx::Rect(0, 0, 1000, 1000));
41  border_contents.SizeAndGetBounds(
42      gfx::Rect(100, 100, 50, 50),  // |position_relative_to|
43      BubbleBorder::TOP_LEFT,
44      false,                        // |allow_bubble_offscreen|
45      gfx::Size(500, 500),          // |contents_size|
46      &contents_bounds, &window_bounds);
47  // The arrow shouldn't have changed from TOP_LEFT.
48  BubbleBorder::ArrowLocation arrow_location =
49      border_contents.bubble_border()->arrow_location();
50  EXPECT_TRUE(BubbleBorder::has_arrow(arrow_location));
51  EXPECT_TRUE(BubbleBorder::is_arrow_on_top(arrow_location));
52  EXPECT_TRUE(BubbleBorder::is_arrow_on_left(arrow_location));
53  EXPECT_GT(window_bounds.x(), 100);
54  EXPECT_GT(window_bounds.y(), 100 + 50 - 10);  // -10 to roughly compensate for
55                                                // arrow overlap.
56
57  // Test bubble not fitting on left.
58  border_contents.SizeAndGetBounds(
59      gfx::Rect(100, 100, 50, 50),  // |position_relative_to|
60      BubbleBorder::TOP_RIGHT,
61      false,                        // |allow_bubble_offscreen|
62      gfx::Size(500, 500),          // |contents_size|
63      &contents_bounds, &window_bounds);
64  arrow_location = border_contents.bubble_border()->arrow_location();
65  // The arrow should have changed to TOP_LEFT.
66  EXPECT_TRUE(BubbleBorder::has_arrow(arrow_location));
67  EXPECT_TRUE(BubbleBorder::is_arrow_on_top(arrow_location));
68  EXPECT_TRUE(BubbleBorder::is_arrow_on_left(arrow_location));
69  EXPECT_GT(window_bounds.x(), 100);
70  EXPECT_GT(window_bounds.y(), 100 + 50 - 10);  // -10 to roughly compensate for
71                                                // arrow overlap.
72
73  // Test bubble not fitting on left or top.
74  border_contents.SizeAndGetBounds(
75      gfx::Rect(100, 100, 50, 50),  // |position_relative_to|
76      BubbleBorder::BOTTOM_RIGHT,
77      false,                        // |allow_bubble_offscreen|
78      gfx::Size(500, 500),          // |contents_size|
79      &contents_bounds, &window_bounds);
80  arrow_location = border_contents.bubble_border()->arrow_location();
81  // The arrow should have changed to TOP_LEFT.
82  EXPECT_TRUE(BubbleBorder::has_arrow(arrow_location));
83  EXPECT_TRUE(BubbleBorder::is_arrow_on_top(arrow_location));
84  EXPECT_TRUE(BubbleBorder::is_arrow_on_left(arrow_location));
85  EXPECT_GT(window_bounds.x(), 100);
86  EXPECT_GT(window_bounds.y(), 100 + 50 - 10);  // -10 to roughly compensate for
87                                                // arrow overlap.
88
89  // Test bubble not fitting on top.
90  border_contents.SizeAndGetBounds(
91      gfx::Rect(100, 100, 50, 50),  // |position_relative_to|
92      BubbleBorder::BOTTOM_LEFT,
93      false,                        // |allow_bubble_offscreen|
94      gfx::Size(500, 500),          // |contents_size|
95      &contents_bounds, &window_bounds);
96  arrow_location = border_contents.bubble_border()->arrow_location();
97  // The arrow should have changed to TOP_LEFT.
98  EXPECT_TRUE(BubbleBorder::has_arrow(arrow_location));
99  EXPECT_TRUE(BubbleBorder::is_arrow_on_top(arrow_location));
100  EXPECT_TRUE(BubbleBorder::is_arrow_on_left(arrow_location));
101  EXPECT_GT(window_bounds.x(), 100);
102  EXPECT_GT(window_bounds.y(), 100 + 50 - 10);  // -10 to roughly compensate for
103                                                // arrow overlap.
104
105  // Test bubble not fitting on top and right.
106  border_contents.SizeAndGetBounds(
107      gfx::Rect(900, 100, 50, 50),  // |position_relative_to|
108      BubbleBorder::BOTTOM_LEFT,
109      false,                        // |allow_bubble_offscreen|
110      gfx::Size(500, 500),          // |contents_size|
111      &contents_bounds, &window_bounds);
112  arrow_location = border_contents.bubble_border()->arrow_location();
113  // The arrow should have changed to TOP_RIGHT.
114  EXPECT_TRUE(BubbleBorder::has_arrow(arrow_location));
115  EXPECT_TRUE(BubbleBorder::is_arrow_on_top(arrow_location));
116  EXPECT_FALSE(BubbleBorder::is_arrow_on_left(arrow_location));
117  EXPECT_LT(window_bounds.x(), 900 + 50 - 500);
118  EXPECT_GT(window_bounds.y(), 100 + 50 - 10);  // -10 to roughly compensate for
119                                                // arrow overlap.
120
121 // Test bubble not fitting on right.
122  border_contents.SizeAndGetBounds(
123      gfx::Rect(900, 100, 50, 50),  // |position_relative_to|
124      BubbleBorder::TOP_LEFT,
125      false,                        // |allow_bubble_offscreen|
126      gfx::Size(500, 500),          // |contents_size|
127      &contents_bounds, &window_bounds);
128  arrow_location = border_contents.bubble_border()->arrow_location();
129  // The arrow should have changed to TOP_RIGHT.
130  EXPECT_TRUE(BubbleBorder::has_arrow(arrow_location));
131  EXPECT_TRUE(BubbleBorder::is_arrow_on_top(arrow_location));
132  EXPECT_FALSE(BubbleBorder::is_arrow_on_left(arrow_location));
133  EXPECT_LT(window_bounds.x(), 900 + 50 - 500);
134  EXPECT_GT(window_bounds.y(), 100 + 50 - 10);  // -10 to roughly compensate for
135                                                // arrow overlap.
136
137  // Test bubble not fitting on bottom and right.
138  border_contents.SizeAndGetBounds(
139      gfx::Rect(900, 900, 50, 50),  // |position_relative_to|
140      BubbleBorder::TOP_LEFT,
141      false,                        // |allow_bubble_offscreen|
142      gfx::Size(500, 500),          // |contents_size|
143      &contents_bounds, &window_bounds);
144  arrow_location = border_contents.bubble_border()->arrow_location();
145  // The arrow should have changed to BOTTOM_RIGHT.
146  EXPECT_TRUE(BubbleBorder::has_arrow(arrow_location));
147  EXPECT_FALSE(BubbleBorder::is_arrow_on_top(arrow_location));
148  EXPECT_FALSE(BubbleBorder::is_arrow_on_left(arrow_location));
149  EXPECT_LT(window_bounds.x(), 900 + 50 - 500);
150  EXPECT_LT(window_bounds.y(), 900 - 500 - 15);  // -15 to roughly compensate
151                                                 // for arrow height.
152
153  // Test bubble not fitting at the bottom.
154  border_contents.SizeAndGetBounds(
155      gfx::Rect(100, 900, 50, 50),  // |position_relative_to|
156      BubbleBorder::TOP_LEFT,
157      false,                        // |allow_bubble_offscreen|
158      gfx::Size(500, 500),          // |contents_size|
159      &contents_bounds, &window_bounds);
160  arrow_location = border_contents.bubble_border()->arrow_location();
161  // The arrow should have changed to BOTTOM_LEFT.
162  EXPECT_TRUE(BubbleBorder::has_arrow(arrow_location));
163  EXPECT_FALSE(BubbleBorder::is_arrow_on_top(arrow_location));
164  EXPECT_TRUE(BubbleBorder::is_arrow_on_left(arrow_location));
165  // The window should be right aligned with the position_relative_to.
166  EXPECT_LT(window_bounds.x(), 900 + 50 - 500);
167  EXPECT_LT(window_bounds.y(), 900 - 500 - 15);  // -15 to roughly compensate
168                                                 // for arrow height.
169
170  // Test bubble not fitting at the bottom and left.
171  border_contents.SizeAndGetBounds(
172      gfx::Rect(100, 900, 50, 50),  // |position_relative_to|
173      BubbleBorder::TOP_RIGHT,
174      false,                        // |allow_bubble_offscreen|
175      gfx::Size(500, 500),          // |contents_size|
176      &contents_bounds, &window_bounds);
177  arrow_location = border_contents.bubble_border()->arrow_location();
178  // The arrow should have changed to BOTTOM_LEFT.
179  EXPECT_TRUE(BubbleBorder::has_arrow(arrow_location));
180  EXPECT_FALSE(BubbleBorder::is_arrow_on_top(arrow_location));
181  EXPECT_TRUE(BubbleBorder::is_arrow_on_left(arrow_location));
182  // The window should be right aligned with the position_relative_to.
183  EXPECT_LT(window_bounds.x(), 900 + 50 - 500);
184  EXPECT_LT(window_bounds.y(), 900 - 500 - 15);  // -15 to roughly compensate
185                                                 // for arrow height.
186}
187
188// Tests that the arrow is not moved when the info-bubble does not fit the
189// screen but moving it would make matter worse.
190TEST_F(BorderContentsTest, BorderContentsSizeAndGetBoundsDontMoveArrow) {
191  TestBorderContents border_contents;
192  border_contents.Init();
193  gfx::Rect contents_bounds;
194  gfx::Rect window_bounds;
195  border_contents.set_monitor_bounds(gfx::Rect(0, 0, 1000, 1000));
196  border_contents.SizeAndGetBounds(
197      gfx::Rect(400, 100, 50, 50),  // |position_relative_to|
198      BubbleBorder::TOP_LEFT,
199      false,                        // |allow_bubble_offscreen|
200      gfx::Size(500, 700),          // |contents_size|
201      &contents_bounds, &window_bounds);
202
203  // The arrow should not have changed, as it would make it the bubble even more
204  // offscreen.
205  BubbleBorder::ArrowLocation arrow_location =
206      border_contents.bubble_border()->arrow_location();
207  EXPECT_TRUE(BubbleBorder::has_arrow(arrow_location));
208  EXPECT_TRUE(BubbleBorder::is_arrow_on_top(arrow_location));
209  EXPECT_TRUE(BubbleBorder::is_arrow_on_left(arrow_location));
210}
211
212// Test that the 'allow offscreen' prevents the bubble from moving.
213TEST_F(BorderContentsTest, BorderContentsSizeAndGetBoundsAllowOffscreen) {
214  TestBorderContents border_contents;
215  border_contents.Init();
216  gfx::Rect contents_bounds;
217  gfx::Rect window_bounds;
218  border_contents.set_monitor_bounds(gfx::Rect(0, 0, 1000, 1000));
219  border_contents.SizeAndGetBounds(
220      gfx::Rect(100, 900, 50, 50),  // |position_relative_to|
221      BubbleBorder::TOP_RIGHT,
222      true,                         // |allow_bubble_offscreen|
223      gfx::Size(500, 500),          // |contents_size|
224      &contents_bounds, &window_bounds);
225
226  // The arrow should not have changed (eventhough the bubble does not fit).
227  BubbleBorder::ArrowLocation arrow_location =
228      border_contents.bubble_border()->arrow_location();
229  EXPECT_TRUE(BubbleBorder::has_arrow(arrow_location));
230  EXPECT_TRUE(BubbleBorder::is_arrow_on_top(arrow_location));
231  EXPECT_FALSE(BubbleBorder::is_arrow_on_left(arrow_location));
232  // The coordinates should be pointing to 'positive relative to' from
233  // TOP_RIGHT.
234  EXPECT_LT(window_bounds.x(), 100 + 50 - 500);
235  EXPECT_GT(window_bounds.y(), 900 + 50 - 10);  // -10 to roughly compensate for
236                                                // arrow overlap.
237}
238