opaque_browser_frame_view_layout_unittest.cc revision 5d1f7b1de12d16ceb2c938c56701a3e8bfa558f7
1// Copyright 2013 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/frame/opaque_browser_frame_view_layout.h"
6
7#include "base/basictypes.h"
8#include "base/command_line.h"
9#include "base/strings/utf_string_conversions.h"
10#include "chrome/browser/ui/views/avatar_label.h"
11#include "chrome/browser/ui/views/avatar_menu_button.h"
12#include "chrome/browser/ui/views/tab_icon_view.h"
13#include "chrome/browser/ui/views/tabs/tab.h"
14#include "chrome/common/chrome_switches.h"
15#include "ui/gfx/image/image_skia.h"
16#include "ui/gfx/image/image_skia_rep.h"
17#include "ui/gfx/text_constants.h"
18#include "ui/views/controls/button/image_button.h"
19#include "ui/views/controls/button/menu_button.h"
20#include "ui/views/controls/label.h"
21#include "ui/views/test/views_test_base.h"
22
23using views::Widget;
24
25namespace {
26
27const int kWidth = 500;
28
29class TestLayoutDelegate : public OpaqueBrowserFrameViewLayoutDelegate {
30 public:
31  enum WindowState {
32    STATE_NORMAL,
33    STATE_MAXIMIZED,
34    STATE_MINIMIZED,
35    STATE_FULLSCREEN
36  };
37
38  TestLayoutDelegate()
39      : show_avatar_(false),
40        show_caption_buttons_(true),
41        window_state_(STATE_NORMAL) {
42  }
43
44  virtual ~TestLayoutDelegate() {}
45
46  void SetWindowTitle(const base::string16& title) {
47    window_title_ = title;
48  }
49
50  void SetShouldShowAvatar(bool show_avatar) {
51    show_avatar_ = show_avatar;
52  }
53
54  void SetShouldShowCaptionButtons(bool show_caption_buttons) {
55    show_caption_buttons_ = show_caption_buttons;
56  }
57
58  void SetWindowState(WindowState state) {
59    window_state_ = state;
60  }
61
62  // OpaqueBrowserFrameViewLayoutDelegate overrides:
63
64  virtual bool ShouldShowWindowIcon() const OVERRIDE {
65    return !window_title_.empty();
66  }
67
68  virtual bool ShouldShowWindowTitle() const OVERRIDE {
69    return !window_title_.empty();
70  }
71
72  virtual base::string16 GetWindowTitle() const OVERRIDE {
73    return window_title_;
74  }
75
76  virtual int GetIconSize() const OVERRIDE {
77    // The value on linux_aura and non-aura windows.
78    return 17;
79  }
80
81  virtual bool ShouldLeaveOffsetNearTopBorder() const OVERRIDE {
82    return !IsMaximized();
83  }
84
85  virtual gfx::Size GetBrowserViewMinimumSize() const OVERRIDE {
86    // Taken from a calculation in BrowserViewLayout.
87    return gfx::Size(168, 64);
88  }
89
90  virtual bool ShouldShowCaptionButtons() const OVERRIDE {
91    return show_caption_buttons_;
92  }
93
94  virtual bool ShouldShowAvatar() const OVERRIDE {
95    return show_avatar_;
96  }
97
98  virtual bool IsRegularOrGuestSession() const OVERRIDE {
99    return true;
100  }
101
102  virtual gfx::ImageSkia GetOTRAvatarIcon() const OVERRIDE {
103    // The calculations depend on the size of the OTR resource, and chromeos
104    // uses a different sized image, so hard code the size of the current
105    // windows/linux one.
106    gfx::ImageSkiaRep rep(gfx::Size(40, 29), 1.0f);
107    gfx::ImageSkia image(rep);
108    return image;
109  }
110
111  virtual bool IsMaximized() const OVERRIDE {
112    return window_state_ == STATE_MAXIMIZED;
113  }
114
115  virtual bool IsMinimized() const OVERRIDE {
116    return window_state_ == STATE_MINIMIZED;
117  }
118
119  virtual bool IsFullscreen() const OVERRIDE {
120    return window_state_ == STATE_FULLSCREEN;
121  }
122
123  virtual bool IsTabStripVisible() const OVERRIDE {
124    return window_title_.empty();
125  }
126
127  virtual int GetTabStripHeight() const OVERRIDE {
128    return IsTabStripVisible() ? Tab::GetMinimumUnselectedSize().height() : 0;
129  }
130
131  virtual int GetAdditionalReservedSpaceInTabStrip() const OVERRIDE {
132    return 0;
133  }
134
135  virtual gfx::Size GetTabstripPreferredSize() const OVERRIDE {
136    // Measured from Tabstrip::GetPreferredSize().
137    return IsTabStripVisible() ? gfx::Size(78, 29) : gfx::Size(0, 0);
138  }
139
140 private:
141  base::string16 window_title_;
142  bool show_avatar_;
143  bool show_caption_buttons_;
144  WindowState window_state_;
145
146  DISALLOW_COPY_AND_ASSIGN(TestLayoutDelegate);
147};
148
149}  // namespace
150
151class OpaqueBrowserFrameViewLayoutTest : public views::ViewsTestBase {
152 public:
153  OpaqueBrowserFrameViewLayoutTest() {}
154  virtual ~OpaqueBrowserFrameViewLayoutTest() {}
155
156  virtual void SetUp() OVERRIDE {
157    views::ViewsTestBase::SetUp();
158
159    delegate_.reset(new TestLayoutDelegate);
160    layout_manager_ = new OpaqueBrowserFrameViewLayout(delegate_.get());
161    layout_manager_->set_extra_caption_y(0);
162    layout_manager_->set_window_caption_spacing(0);
163    widget_ = new Widget;
164    widget_->Init(CreateParams(Widget::InitParams::TYPE_POPUP));
165    root_view_ = widget_->GetRootView();
166    root_view_->SetSize(gfx::Size(kWidth, kWidth));
167    root_view_->SetLayoutManager(layout_manager_);
168
169    // Add the caption buttons. We use fake images because we're modeling the
170    // Windows assets here, while the linux version uses differently sized
171    // assets.
172    //
173    // TODO(erg): In a follow up patch, separate these sizes out into virtual
174    // accessors so we can test both the windows and linux behaviours once we
175    // start modifying the code.
176    minimize_button_ = InitWindowCaptionButton(
177        VIEW_ID_MINIMIZE_BUTTON, gfx::Size(26, 18));
178    maximize_button_ = InitWindowCaptionButton(
179        VIEW_ID_MAXIMIZE_BUTTON, gfx::Size(25, 18));
180    restore_button_ = InitWindowCaptionButton(
181        VIEW_ID_RESTORE_BUTTON, gfx::Size(25, 18));
182    close_button_ = InitWindowCaptionButton(
183        VIEW_ID_CLOSE_BUTTON, gfx::Size(43, 18));
184  }
185
186  virtual void TearDown() OVERRIDE {
187    widget_->CloseNow();
188
189    views::ViewsTestBase::TearDown();
190  }
191
192 protected:
193  views::ImageButton* InitWindowCaptionButton(ViewID view_id,
194                                              const gfx::Size& size) {
195    views::ImageButton* button = new views::ImageButton(NULL);
196    gfx::ImageSkiaRep rep(size, 1.0f);
197    gfx::ImageSkia image(rep);
198    button->SetImage(views::CustomButton::STATE_NORMAL, &image);
199    button->set_id(view_id);
200    root_view_->AddChildView(button);
201    return button;
202  }
203
204  void AddWindowTitleIcons() {
205    tab_icon_view_ = new TabIconView(NULL, NULL);
206    tab_icon_view_->set_is_light(true);
207    tab_icon_view_->set_id(VIEW_ID_WINDOW_ICON);
208    root_view_->AddChildView(tab_icon_view_);
209
210    window_title_ = new views::Label(delegate_->GetWindowTitle());
211    window_title_->SetVisible(delegate_->ShouldShowWindowTitle());
212    window_title_->SetEnabledColor(SK_ColorWHITE);
213    window_title_->SetBackgroundColor(0x00000000);
214    window_title_->SetHorizontalAlignment(gfx::ALIGN_LEFT);
215    window_title_->set_id(VIEW_ID_WINDOW_TITLE);
216    root_view_->AddChildView(window_title_);
217  }
218
219  void AddAvatarButton() {
220    menu_button_ = new AvatarMenuButton(NULL, false);
221    menu_button_->set_id(VIEW_ID_AVATAR_BUTTON);
222    delegate_->SetShouldShowAvatar(true);
223    root_view_->AddChildView(menu_button_);
224  }
225
226  void AddAvatarLabel() {
227    avatar_label_ = new AvatarLabel(NULL);
228    avatar_label_->set_id(VIEW_ID_AVATAR_LABEL);
229    root_view_->AddChildView(avatar_label_);
230
231    // The avatar label should only be used together with the avatar button.
232    AddAvatarButton();
233  }
234
235  void AddNewAvatarButton() {
236   new_avatar_button_ =
237       new views::MenuButton(NULL, base::string16(), NULL, false);
238   new_avatar_button_->set_id(VIEW_ID_NEW_AVATAR_BUTTON);
239   root_view_->AddChildView(new_avatar_button_);
240  }
241
242  void ExpectBasicWindowBounds() {
243    EXPECT_EQ("428,1 25x18", maximize_button_->bounds().ToString());
244    EXPECT_EQ("402,1 26x18", minimize_button_->bounds().ToString());
245    EXPECT_EQ("0,0 0x0", restore_button_->bounds().ToString());
246    EXPECT_EQ("453,1 43x18", close_button_->bounds().ToString());
247  }
248
249  Widget* widget_;
250  views::View* root_view_;
251  OpaqueBrowserFrameViewLayout* layout_manager_;
252  scoped_ptr<TestLayoutDelegate> delegate_;
253
254  // Widgets:
255  views::ImageButton* minimize_button_;
256  views::ImageButton* maximize_button_;
257  views::ImageButton* restore_button_;
258  views::ImageButton* close_button_;
259
260  TabIconView* tab_icon_view_;
261  views::Label* window_title_;
262
263  AvatarLabel* avatar_label_;
264  AvatarMenuButton* menu_button_;
265  views::MenuButton* new_avatar_button_;
266
267  DISALLOW_COPY_AND_ASSIGN(OpaqueBrowserFrameViewLayoutTest);
268};
269
270TEST_F(OpaqueBrowserFrameViewLayoutTest, BasicWindow) {
271  // Tests the layout of a default chrome window with no avatars, no window
272  // titles, and a tabstrip.
273  root_view_->Layout();
274
275  ExpectBasicWindowBounds();
276
277  // After some visual inspection, it really does look like the tabstrip is
278  // initally positioned out of our view.
279  EXPECT_EQ("-1,13 398x29",
280            layout_manager_->GetBoundsForTabStrip(
281                delegate_->GetTabstripPreferredSize(), kWidth).ToString());
282  EXPECT_EQ("261x73", layout_manager_->GetMinimumSize(kWidth).ToString());
283
284  // A normal window with no window icon still produces icon bounds for
285  // Windows, which has a hidden icon that a user can double click on to close
286  // the window.
287  EXPECT_EQ("6,4 17x17", layout_manager_->IconBounds().ToString());
288}
289
290TEST_F(OpaqueBrowserFrameViewLayoutTest, BasicWindowMaximized) {
291  // Tests the layout of a default chrome window with no avatars, no window
292  // titles, and a tabstrip, but maximized this time.
293  delegate_->SetWindowState(TestLayoutDelegate::STATE_MAXIMIZED);
294  root_view_->Layout();
295
296  // Note how the bounds start at the exact top of the window while maximized
297  // while they start 1 pixel below when unmaximized.
298  EXPECT_EQ("0,0 0x0", maximize_button_->bounds().ToString());
299  EXPECT_EQ("403,0 26x18", minimize_button_->bounds().ToString());
300  EXPECT_EQ("429,0 25x18", restore_button_->bounds().ToString());
301  EXPECT_EQ("454,0 46x18", close_button_->bounds().ToString());
302
303  EXPECT_EQ("-5,-3 392x29",
304            layout_manager_->GetBoundsForTabStrip(
305                delegate_->GetTabstripPreferredSize(), kWidth).ToString());
306  EXPECT_EQ("262x61", layout_manager_->GetMinimumSize(kWidth).ToString());
307
308  // In the maximized case, OpaqueBrowserFrameView::NonClientHitTest() uses
309  // this rect, extended to the top left corner of the window.
310  EXPECT_EQ("2,0 17x17", layout_manager_->IconBounds().ToString());
311}
312
313TEST_F(OpaqueBrowserFrameViewLayoutTest, MaximizedWithYOffset) {
314  // Tests the layout of a basic chrome window with the caption buttons slightly
315  // offset from the top of the screen (as they are on Linux).
316  layout_manager_->set_extra_caption_y(2);
317  delegate_->SetWindowState(TestLayoutDelegate::STATE_MAXIMIZED);
318  root_view_->Layout();
319
320  // Note how the bounds start at the exact top of the window, DESPITE the
321  // caption Y offset of 2. This ensures that we obey Fitts' Law (the buttons
322  // are clickable on the top edge of the screen). However, the buttons are 2
323  // pixels taller, so the images appear to be offset by 2 pixels.
324  EXPECT_EQ("0,0 0x0", maximize_button_->bounds().ToString());
325  EXPECT_EQ("403,0 26x20", minimize_button_->bounds().ToString());
326  EXPECT_EQ("429,0 25x20", restore_button_->bounds().ToString());
327  EXPECT_EQ("454,0 46x20", close_button_->bounds().ToString());
328
329  EXPECT_EQ("-5,-3 392x29",
330            layout_manager_->GetBoundsForTabStrip(
331                delegate_->GetTabstripPreferredSize(), kWidth).ToString());
332  EXPECT_EQ("262x61", layout_manager_->GetMinimumSize(kWidth).ToString());
333
334  // In the maximized case, OpaqueBrowserFrameView::NonClientHitTest() uses
335  // this rect, extended to the top left corner of the window.
336  EXPECT_EQ("2,0 17x17", layout_manager_->IconBounds().ToString());
337}
338
339TEST_F(OpaqueBrowserFrameViewLayoutTest, WindowButtonsOnLeft) {
340  // Tests the layout of a chrome window with caption buttons on the left.
341  std::vector<views::FrameButton> leading_buttons;
342  std::vector<views::FrameButton> trailing_buttons;
343  leading_buttons.push_back(views::FRAME_BUTTON_CLOSE);
344  leading_buttons.push_back(views::FRAME_BUTTON_MINIMIZE);
345  leading_buttons.push_back(views::FRAME_BUTTON_MAXIMIZE);
346  layout_manager_->SetButtonOrdering(leading_buttons, trailing_buttons);
347  root_view_->Layout();
348
349  EXPECT_EQ("73,1 25x18", maximize_button_->bounds().ToString());
350  EXPECT_EQ("47,1 26x18", minimize_button_->bounds().ToString());
351  EXPECT_EQ("0,0 0x0", restore_button_->bounds().ToString());
352  EXPECT_EQ("4,1 43x18", close_button_->bounds().ToString());
353
354  EXPECT_EQ("93,13 398x29",
355            layout_manager_->GetBoundsForTabStrip(
356                delegate_->GetTabstripPreferredSize(), kWidth).ToString());
357  EXPECT_EQ("261x73", layout_manager_->GetMinimumSize(kWidth).ToString());
358
359  // If the buttons are on the left, there should be no hidden icon for the user
360  // to double click.
361  EXPECT_EQ("0,0 0x0", layout_manager_->IconBounds().ToString());
362}
363
364TEST_F(OpaqueBrowserFrameViewLayoutTest, WithoutCaptionButtons) {
365  // Tests the layout of a default chrome window with no caption buttons (which
366  // should force the tab strip to be condensed).
367  delegate_->SetShouldShowCaptionButtons(false);
368  root_view_->Layout();
369
370  EXPECT_EQ("0,0 0x0", maximize_button_->bounds().ToString());
371  EXPECT_EQ("0,0 0x0", minimize_button_->bounds().ToString());
372  EXPECT_EQ("0,0 0x0", restore_button_->bounds().ToString());
373  EXPECT_EQ("0,0 0x0", close_button_->bounds().ToString());
374
375  EXPECT_EQ("-5,-3 500x29",
376            layout_manager_->GetBoundsForTabStrip(
377                delegate_->GetTabstripPreferredSize(), kWidth).ToString());
378  EXPECT_EQ("251x61", layout_manager_->GetMinimumSize(kWidth).ToString());
379
380  // A normal window with no window icon still produces icon bounds for
381  // Windows, which has a hidden icon that a user can double click on to close
382  // the window.
383  EXPECT_EQ("2,0 17x17", layout_manager_->IconBounds().ToString());
384}
385
386TEST_F(OpaqueBrowserFrameViewLayoutTest, MaximizedWithoutCaptionButtons) {
387  // Tests the layout of a maximized chrome window with no caption buttons.
388  delegate_->SetWindowState(TestLayoutDelegate::STATE_MAXIMIZED);
389  delegate_->SetShouldShowCaptionButtons(false);
390  root_view_->Layout();
391
392  EXPECT_EQ("0,0 0x0", maximize_button_->bounds().ToString());
393  EXPECT_EQ("0,0 0x0", minimize_button_->bounds().ToString());
394  EXPECT_EQ("0,0 0x0", restore_button_->bounds().ToString());
395  EXPECT_EQ("0,0 0x0", close_button_->bounds().ToString());
396
397  EXPECT_EQ("-5,-3 500x29",
398            layout_manager_->GetBoundsForTabStrip(
399                delegate_->GetTabstripPreferredSize(), kWidth).ToString());
400  EXPECT_EQ("251x61", layout_manager_->GetMinimumSize(kWidth).ToString());
401
402  // In the maximized case, OpaqueBrowserFrameView::NonClientHitTest() uses
403  // this rect, extended to the top left corner of the window.
404  EXPECT_EQ("2,0 17x17", layout_manager_->IconBounds().ToString());
405}
406
407TEST_F(OpaqueBrowserFrameViewLayoutTest, WithWindowTitleAndIcon) {
408  // Tests the layout of pop up windows.
409  delegate_->SetWindowTitle(base::ASCIIToUTF16("Window Title"));
410  AddWindowTitleIcons();
411  root_view_->Layout();
412
413  // We should have the right hand side should match the BasicWindow case.
414  ExpectBasicWindowBounds();
415
416  // Check the location of the tab icon and window title.
417  EXPECT_EQ("6,3 17x17", tab_icon_view_->bounds().ToString());
418  EXPECT_EQ("27,3 370x17", window_title_->bounds().ToString());
419}
420
421TEST_F(OpaqueBrowserFrameViewLayoutTest, WindowWithAvatar) {
422  // Tests a normal tabstrip window with an avatar icon.
423  AddAvatarButton();
424  root_view_->Layout();
425
426  ExpectBasicWindowBounds();
427
428  // Check the location of the avatar
429  EXPECT_EQ("7,11 40x29", menu_button_->bounds().ToString());
430  EXPECT_EQ("45,13 352x29",
431            layout_manager_->GetBoundsForTabStrip(
432                delegate_->GetTabstripPreferredSize(), kWidth).ToString());
433  EXPECT_EQ("261x73", layout_manager_->GetMinimumSize(kWidth).ToString());
434}
435
436TEST_F(OpaqueBrowserFrameViewLayoutTest, WindowWithAvatarWithButtonsOnLeft) {
437  // Tests the layout of a chrome window with an avatar icon and caption buttons
438  // on the left. The avatar icon should therefore be on the right.
439  // AddAvatarLabel() also adds the avatar button.
440  AddAvatarLabel();
441  std::vector<views::FrameButton> leading_buttons;
442  std::vector<views::FrameButton> trailing_buttons;
443  leading_buttons.push_back(views::FRAME_BUTTON_CLOSE);
444  leading_buttons.push_back(views::FRAME_BUTTON_MINIMIZE);
445  leading_buttons.push_back(views::FRAME_BUTTON_MAXIMIZE);
446  layout_manager_->SetButtonOrdering(leading_buttons, trailing_buttons);
447  root_view_->Layout();
448
449  EXPECT_EQ("73,1 25x18", maximize_button_->bounds().ToString());
450  EXPECT_EQ("47,1 26x18", minimize_button_->bounds().ToString());
451  EXPECT_EQ("0,0 0x0", restore_button_->bounds().ToString());
452  EXPECT_EQ("4,1 43x18", close_button_->bounds().ToString());
453
454  // Check the location of the avatar
455  EXPECT_EQ("454,11 40x29", menu_button_->bounds().ToString());
456
457  // Check the tab strip bounds.
458  gfx::Rect tab_strip_bounds = layout_manager_->GetBoundsForTabStrip(
459      delegate_->GetTabstripPreferredSize(), kWidth);
460  EXPECT_GT(tab_strip_bounds.x(), maximize_button_->bounds().x());
461  EXPECT_GT(maximize_button_->bounds().right(), tab_strip_bounds.x());
462  EXPECT_EQ(13, tab_strip_bounds.y());
463  EXPECT_EQ(29, tab_strip_bounds.height());
464  EXPECT_GT(avatar_label_->bounds().x(), tab_strip_bounds.right());
465  EXPECT_EQ("261x73", layout_manager_->GetMinimumSize(kWidth).ToString());
466
467  // Check the relative location of the avatar label to the avatar. The right
468  // end of the avatar label should be slightly to the right of the right end of
469  // the avatar icon.
470  EXPECT_GT(avatar_label_->bounds().right(), menu_button_->bounds().right());
471  EXPECT_GT(menu_button_->bounds().x(), avatar_label_->bounds().x());
472  EXPECT_GT(menu_button_->bounds().bottom(),
473            avatar_label_->bounds().bottom());
474  EXPECT_GT(avatar_label_->bounds().y(), menu_button_->bounds().y());
475
476  // This means that the menu will pop out facing the left (if it were to face
477  // the right, it would go outside the window frame and be clipped).
478  EXPECT_TRUE(menu_button_->button_on_right());
479
480  // If the buttons are on the left, there should be no hidden icon for the user
481  // to double click.
482  EXPECT_EQ("0,0 0x0", layout_manager_->IconBounds().ToString());
483}
484
485TEST_F(OpaqueBrowserFrameViewLayoutTest,
486       WindowWithAvatarWithoutCaptionButtonsOnLeft) {
487  // Tests the layout of a chrome window with an avatar icon and no caption
488  // buttons. However, the caption buttons *would* be on the left if they
489  // weren't hidden, and therefore, the avatar icon should be on the right.
490  // The lack of caption buttons should force the tab strip to be condensed.
491  AddAvatarButton();
492  std::vector<views::FrameButton> leading_buttons;
493  std::vector<views::FrameButton> trailing_buttons;
494  leading_buttons.push_back(views::FRAME_BUTTON_CLOSE);
495  leading_buttons.push_back(views::FRAME_BUTTON_MINIMIZE);
496  leading_buttons.push_back(views::FRAME_BUTTON_MAXIMIZE);
497  layout_manager_->SetButtonOrdering(leading_buttons, trailing_buttons);
498  delegate_->SetShouldShowCaptionButtons(false);
499  root_view_->Layout();
500
501  EXPECT_EQ("0,0 0x0", maximize_button_->bounds().ToString());
502  EXPECT_EQ("0,0 0x0", minimize_button_->bounds().ToString());
503  EXPECT_EQ("0,0 0x0", restore_button_->bounds().ToString());
504  EXPECT_EQ("0,0 0x0", close_button_->bounds().ToString());
505
506  // Check the location of the avatar
507  EXPECT_EQ("458,0 40x24", menu_button_->bounds().ToString());
508  EXPECT_EQ("-5,-3 458x29",
509            layout_manager_->GetBoundsForTabStrip(
510                delegate_->GetTabstripPreferredSize(), kWidth).ToString());
511  EXPECT_EQ("251x61", layout_manager_->GetMinimumSize(kWidth).ToString());
512
513  // A normal window with no window icon still produces icon bounds for
514  // Windows, which has a hidden icon that a user can double click on to close
515  // the window.
516  EXPECT_EQ("2,0 17x17", layout_manager_->IconBounds().ToString());
517}
518
519TEST_F(OpaqueBrowserFrameViewLayoutTest, WindowWithNewAvatar) {
520  CommandLine::ForCurrentProcess()->AppendSwitch(
521      switches::kNewProfileManagement);
522
523  // Tests a normal tabstrip window with the new style avatar icon.
524  AddNewAvatarButton();
525  root_view_->Layout();
526
527  ExpectBasicWindowBounds();
528
529  // Check the location of the caption button
530  EXPECT_EQ("385,1 12x20", new_avatar_button_->bounds().ToString());
531  // The basic window bounds are (-1, 13 398x29). There should not be an icon
532  // avatar in the left, and the new avatar button has an offset of 5 to its
533  // next control.
534  EXPECT_EQ("-1,13 381x29",
535            layout_manager_->GetBoundsForTabStrip(
536                delegate_->GetTabstripPreferredSize(), kWidth).ToString());
537  EXPECT_EQ("261x73", layout_manager_->GetMinimumSize(kWidth).ToString());
538}
539
540TEST_F(OpaqueBrowserFrameViewLayoutTest, WindowWithAvatarLabelAndButtonOnLeft) {
541  AddAvatarLabel();
542  root_view_->Layout();
543
544  ExpectBasicWindowBounds();
545
546  // Check the location of the avatar label relative to the avatar button if
547  // both are displayed on the left side.
548  // The label height and width depends on the font size and the text displayed.
549  // This may possibly change, so we don't test it here.
550  EXPECT_EQ(menu_button_->bounds().x() - 2, avatar_label_->bounds().x());
551  EXPECT_EQ(
552      menu_button_->bounds().bottom() - 3 - avatar_label_->bounds().height(),
553      avatar_label_->bounds().y());
554}
555