Blink roll 174234:174238
[chromium-blink-merge.git] / ui / views / window / dialog_client_view_unittest.cc
blob28b001f2d281b6d63828016aa6bc724f2fd914d3
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/basictypes.h"
6 #include "base/strings/utf_string_conversions.h"
7 #include "ui/base/ui_base_types.h"
8 #include "ui/views/controls/button/label_button.h"
9 #include "ui/views/test/test_views.h"
10 #include "ui/views/test/views_test_base.h"
11 #include "ui/views/widget/widget.h"
12 #include "ui/views/window/dialog_client_view.h"
13 #include "ui/views/window/dialog_delegate.h"
15 namespace views {
17 class TestDialogClientView : public DialogClientView {
18 public:
19 TestDialogClientView(View* contents_view,
20 DialogDelegate* dialog_delegate)
21 : DialogClientView(contents_view),
22 dialog_(dialog_delegate) {}
23 virtual ~TestDialogClientView() {}
25 // DialogClientView implementation.
26 virtual DialogDelegate* GetDialogDelegate() const OVERRIDE { return dialog_; }
28 View* GetContentsView() { return contents_view(); }
30 void CreateExtraViews() {
31 CreateExtraView();
32 CreateFootnoteView();
35 private:
36 DialogDelegate* dialog_;
38 DISALLOW_COPY_AND_ASSIGN(TestDialogClientView);
41 class DialogClientViewTest : public ViewsTestBase,
42 public DialogDelegateView {
43 public:
44 DialogClientViewTest()
45 : dialog_buttons_(ui::DIALOG_BUTTON_NONE),
46 extra_view_(NULL),
47 footnote_view_(NULL) {}
48 virtual ~DialogClientViewTest() {}
50 // testing::Test implementation.
51 virtual void SetUp() OVERRIDE {
52 dialog_buttons_ = ui::DIALOG_BUTTON_NONE;
53 contents_.reset(new StaticSizedView(gfx::Size(100, 200)));
54 client_view_.reset(new TestDialogClientView(contents_.get(), this));
56 ViewsTestBase::SetUp();
59 // DialogDelegateView implementation.
60 virtual View* GetContentsView() OVERRIDE { return contents_.get(); }
61 virtual View* CreateExtraView() OVERRIDE { return extra_view_; }
62 virtual View* CreateFootnoteView() OVERRIDE { return footnote_view_; }
63 virtual int GetDialogButtons() const OVERRIDE { return dialog_buttons_; }
65 protected:
66 gfx::Rect GetUpdatedClientBounds() {
67 client_view_->SizeToPreferredSize();
68 client_view_->Layout();
69 return client_view_->bounds();
72 // Makes sure that the content view is sized correctly. Width must be at least
73 // the requested amount, but height should always match exactly.
74 void CheckContentsIsSetToPreferredSize() {
75 const gfx::Rect client_bounds = GetUpdatedClientBounds();
76 const gfx::Size preferred_size = contents_->GetPreferredSize();
77 EXPECT_EQ(preferred_size.height(), contents_->bounds().height());
78 EXPECT_LE(preferred_size.width(), contents_->bounds().width());
79 EXPECT_EQ(contents_->bounds().origin(), client_bounds.origin());
80 EXPECT_EQ(contents_->bounds().right(), client_bounds.right());
83 // Sets the buttons to show in the dialog and refreshes the dialog.
84 void SetDialogButtons(int dialog_buttons) {
85 dialog_buttons_ = dialog_buttons;
86 client_view_->UpdateDialogButtons();
89 // Sets the extra view.
90 void SetExtraView(View* view) {
91 DCHECK(!extra_view_);
92 extra_view_ = view;
93 client_view_->CreateExtraViews();
96 // Sets the footnote view.
97 void SetFootnoteView(View* view) {
98 DCHECK(!footnote_view_);
99 footnote_view_ = view;
100 client_view_->CreateExtraViews();
103 TestDialogClientView* client_view() { return client_view_.get(); }
105 private:
106 // The contents of the dialog.
107 scoped_ptr<View> contents_;
108 // The DialogClientView that's being tested.
109 scoped_ptr<TestDialogClientView> client_view_;
110 // The bitmask of buttons to show in the dialog.
111 int dialog_buttons_;
112 View* extra_view_; // weak
113 View* footnote_view_; // weak
115 DISALLOW_COPY_AND_ASSIGN(DialogClientViewTest);
118 TEST_F(DialogClientViewTest, UpdateButtons) {
119 // This dialog should start with no buttons.
120 EXPECT_EQ(GetDialogButtons(), ui::DIALOG_BUTTON_NONE);
121 EXPECT_EQ(NULL, client_view()->ok_button());
122 EXPECT_EQ(NULL, client_view()->cancel_button());
123 const int height_without_buttons = GetUpdatedClientBounds().height();
125 // Update to use both buttons.
126 SetDialogButtons(ui::DIALOG_BUTTON_OK | ui::DIALOG_BUTTON_CANCEL);
127 EXPECT_TRUE(client_view()->ok_button()->is_default());
128 EXPECT_FALSE(client_view()->cancel_button()->is_default());
129 const int height_with_buttons = GetUpdatedClientBounds().height();
130 EXPECT_GT(height_with_buttons, height_without_buttons);
132 // Remove the dialog buttons.
133 SetDialogButtons(ui::DIALOG_BUTTON_NONE);
134 EXPECT_EQ(NULL, client_view()->ok_button());
135 EXPECT_EQ(NULL, client_view()->cancel_button());
136 EXPECT_EQ(GetUpdatedClientBounds().height(), height_without_buttons);
138 // Reset with just an ok button.
139 SetDialogButtons(ui::DIALOG_BUTTON_OK);
140 EXPECT_TRUE(client_view()->ok_button()->is_default());
141 EXPECT_EQ(NULL, client_view()->cancel_button());
142 EXPECT_EQ(GetUpdatedClientBounds().height(), height_with_buttons);
144 // Reset with just a cancel button.
145 SetDialogButtons(ui::DIALOG_BUTTON_CANCEL);
146 EXPECT_EQ(NULL, client_view()->ok_button());
147 EXPECT_TRUE(client_view()->cancel_button()->is_default());
148 EXPECT_EQ(GetUpdatedClientBounds().height(), height_with_buttons);
151 TEST_F(DialogClientViewTest, RemoveAndUpdateButtons) {
152 // Removing buttons from another context should clear the local pointer.
153 SetDialogButtons(ui::DIALOG_BUTTON_OK | ui::DIALOG_BUTTON_CANCEL);
154 delete client_view()->ok_button();
155 EXPECT_EQ(NULL, client_view()->ok_button());
156 delete client_view()->cancel_button();
157 EXPECT_EQ(NULL, client_view()->cancel_button());
159 // Updating should restore the requested buttons properly.
160 SetDialogButtons(ui::DIALOG_BUTTON_OK | ui::DIALOG_BUTTON_CANCEL);
161 EXPECT_TRUE(client_view()->ok_button()->is_default());
162 EXPECT_FALSE(client_view()->cancel_button()->is_default());
165 // Test that the contents view gets its preferred size in the basic dialog
166 // configuration.
167 TEST_F(DialogClientViewTest, ContentsSize) {
168 CheckContentsIsSetToPreferredSize();
169 EXPECT_EQ(GetContentsView()->bounds().bottom(),
170 client_view()->bounds().bottom());
173 // Test the effect of the button strip on layout.
174 TEST_F(DialogClientViewTest, LayoutWithButtons) {
175 SetDialogButtons(ui::DIALOG_BUTTON_OK | ui::DIALOG_BUTTON_CANCEL);
176 CheckContentsIsSetToPreferredSize();
177 EXPECT_LT(GetContentsView()->bounds().bottom(),
178 client_view()->bounds().bottom());
179 gfx::Size no_extra_view_size = client_view()->bounds().size();
181 View* extra_view = new StaticSizedView(gfx::Size(200, 200));
182 SetExtraView(extra_view);
183 CheckContentsIsSetToPreferredSize();
184 EXPECT_GT(client_view()->bounds().height(), no_extra_view_size.height());
185 int width_of_extra_view = extra_view->bounds().width();
187 // Visibility of extra view is respected.
188 extra_view->SetVisible(false);
189 CheckContentsIsSetToPreferredSize();
190 EXPECT_EQ(no_extra_view_size.height(), client_view()->bounds().height());
191 EXPECT_EQ(no_extra_view_size.width(), client_view()->bounds().width());
193 // Try with a reduced-size dialog.
194 extra_view->SetVisible(true);
195 client_view()->SetBoundsRect(gfx::Rect(gfx::Point(0, 0), no_extra_view_size));
196 client_view()->Layout();
197 DCHECK_GT(width_of_extra_view, extra_view->bounds().width());
200 // Test the effect of the footnote view on layout.
201 TEST_F(DialogClientViewTest, LayoutWithFootnote) {
202 CheckContentsIsSetToPreferredSize();
203 gfx::Size no_footnote_size = client_view()->bounds().size();
205 View* footnote_view = new StaticSizedView(gfx::Size(200, 200));
206 SetFootnoteView(footnote_view);
207 CheckContentsIsSetToPreferredSize();
208 EXPECT_GT(client_view()->bounds().height(), no_footnote_size.height());
209 EXPECT_EQ(200, footnote_view->bounds().height());
210 gfx::Size with_footnote_size = client_view()->bounds().size();
211 EXPECT_EQ(with_footnote_size.width(), footnote_view->bounds().width());
213 SetDialogButtons(ui::DIALOG_BUTTON_CANCEL);
214 CheckContentsIsSetToPreferredSize();
215 EXPECT_LE(with_footnote_size.height(), client_view()->bounds().height());
216 EXPECT_LE(with_footnote_size.width(), client_view()->bounds().width());
217 gfx::Size with_footnote_and_button_size = client_view()->bounds().size();
219 SetDialogButtons(ui::DIALOG_BUTTON_NONE);
220 footnote_view->SetVisible(false);
221 CheckContentsIsSetToPreferredSize();
222 EXPECT_EQ(no_footnote_size.height(), client_view()->bounds().height());
223 EXPECT_EQ(no_footnote_size.width(), client_view()->bounds().width());
226 // Test that GetHeightForWidth is respected for the footnote view.
227 TEST_F(DialogClientViewTest, LayoutWithFootnoteHeightForWidth) {
228 CheckContentsIsSetToPreferredSize();
229 gfx::Size no_footnote_size = client_view()->bounds().size();
231 View* footnote_view = new ProportionallySizedView(3);
232 SetFootnoteView(footnote_view);
233 CheckContentsIsSetToPreferredSize();
234 EXPECT_GT(client_view()->bounds().height(), no_footnote_size.height());
235 EXPECT_EQ(footnote_view->bounds().width() * 3,
236 footnote_view->bounds().height());
239 // Test that the DialogClientView's FocusManager is properly updated when the
240 // DialogClientView belongs to a non top level widget and the widget is
241 // reparented. The DialogClientView belongs to a non top level widget in the
242 // case of constrained windows. The constrained window's widget is reparented
243 // when a browser tab is dragged to a different browser window.
244 TEST_F(DialogClientViewTest, FocusManager) {
245 scoped_ptr<Widget> toplevel1(new Widget);
246 Widget::InitParams toplevel1_params =
247 CreateParams(Widget::InitParams::TYPE_WINDOW);
248 toplevel1_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
249 toplevel1->Init(toplevel1_params);
251 scoped_ptr<Widget> toplevel2(new Widget);
252 Widget::InitParams toplevel2_params =
253 CreateParams(Widget::InitParams::TYPE_WINDOW);
254 toplevel2_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
255 toplevel2->Init(toplevel2_params);
257 Widget* dialog = new Widget;
258 Widget::InitParams dialog_params =
259 CreateParams(Widget::InitParams::TYPE_WINDOW);
260 dialog_params.child = true;
261 dialog_params.delegate = new DialogDelegateView();
262 dialog_params.parent = toplevel1->GetNativeView();
263 dialog->Init(dialog_params);
265 // Test that the FocusManager has been properly set when the DialogClientView
266 // was parented to |dialog|.
267 DialogClientView* client_view =
268 static_cast<DialogClientView*>(dialog->client_view());
269 EXPECT_EQ(toplevel1->GetFocusManager(), client_view->focus_manager_);
271 // Test that the FocusManager is properly updated when the DialogClientView's
272 // top level widget is changed.
273 Widget::ReparentNativeView(dialog->GetNativeView(), NULL);
274 EXPECT_EQ(NULL, client_view->focus_manager_);
275 Widget::ReparentNativeView(dialog->GetNativeView(),
276 toplevel2->GetNativeView());
277 EXPECT_EQ(toplevel2->GetFocusManager(), client_view->focus_manager_);
278 Widget::ReparentNativeView(dialog->GetNativeView(),
279 toplevel1->GetNativeView());
280 EXPECT_NE(toplevel1->GetFocusManager(), toplevel2->GetFocusManager());
281 EXPECT_EQ(toplevel1->GetFocusManager(), client_view->focus_manager_);
283 // Test that the FocusManager is properly cleared when the DialogClientView is
284 // removed from |dialog| during the widget's destruction.
285 client_view->set_owned_by_client();
286 scoped_ptr<DialogClientView> owned_client_view(client_view);
287 toplevel1->CloseNow();
288 toplevel2->CloseNow();
289 EXPECT_EQ(NULL, owned_client_view->focus_manager_);
292 } // namespace views