1// Copyright 2014 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 "athena/home/athena_start_page_view.h"
6
7#include "athena/home/home_card_constants.h"
8#include "athena/test/athena_test_base.h"
9#include "base/format_macros.h"
10#include "base/strings/stringprintf.h"
11#include "base/strings/utf_string_conversions.h"
12#include "ui/app_list/app_list_switches.h"
13#include "ui/app_list/search_box_model.h"
14#include "ui/app_list/test/app_list_test_model.h"
15#include "ui/app_list/test/app_list_test_view_delegate.h"
16#include "ui/app_list/views/search_box_view.h"
17#include "ui/gfx/geometry/rect.h"
18#include "ui/views/controls/textfield/textfield.h"
19
20namespace athena {
21
22namespace {
23
24// The number of dummy applications in this tetst.
25const size_t kNumApps = 10;
26
27}
28
29class AthenaTestViewDelegate : public app_list::test::AppListTestViewDelegate {
30 public:
31  AthenaTestViewDelegate() {}
32  virtual ~AthenaTestViewDelegate() {}
33
34 private:
35  // app_list::AppListViewDelegate:
36  virtual views::View* CreateStartPageWebView(const gfx::Size& size) OVERRIDE {
37    return new views::View();
38  }
39
40  DISALLOW_COPY_AND_ASSIGN(AthenaTestViewDelegate);
41};
42
43class AthenaStartPageViewTest : public test::AthenaTestBase {
44 public:
45  AthenaStartPageViewTest() {}
46  virtual ~AthenaStartPageViewTest() {}
47
48  // testing::Test:
49  virtual void SetUp() OVERRIDE {
50    test::AthenaTestBase::SetUp();
51    app_list::test::AppListTestModel* model = view_delegate_.GetTestModel();
52    for (size_t i = 0; i < kNumApps; ++i) {
53      model->AddItem(new app_list::test::AppListTestModel::AppListTestItem(
54          base::StringPrintf("id-%" PRIuS, i), model));
55    }
56
57    view_.reset(new AthenaStartPageView(&view_delegate_));
58    SetSize(gfx::Size(1280, 800));
59  }
60  virtual void TearDown() OVERRIDE {
61    view_.reset();
62    test::AthenaTestBase::TearDown();
63  }
64
65 protected:
66  void SetSize(const gfx::Size& new_size) {
67    view_->SetSize(new_size);
68    view_->Layout();
69  }
70
71  gfx::Rect GetIconsBounds() const {
72    return view_->app_icon_container_->layer()->GetTargetBounds();
73  }
74
75  gfx::Rect GetControlBounds() const {
76    return view_->control_icon_container_->layer()->GetTargetBounds();
77  }
78
79  gfx::Rect GetSearchBoxBounds() const {
80    return view_->search_box_container_->layer()->GetTargetBounds();
81  }
82
83  gfx::Rect GetLogoBounds() const {
84    return view_->logo_->layer()->GetTargetBounds();
85  }
86
87  bool IsLogoVisible() const {
88    return view_->logo_->layer()->GetTargetOpacity() > 0 &&
89        view_->logo_->layer()->GetTargetVisibility();
90  }
91
92  gfx::Size GetSearchBoxPreferredSize() {
93    return view_->search_box_container_->GetPreferredSize();
94  }
95
96  void SetSearchQuery(const base::string16& query) {
97    view_delegate_.GetModel()->search_box()->SetText(query);
98  }
99
100  base::string16 GetVisibleQuery() {
101    return view_->search_box_view_->search_box()->text();
102  }
103
104  scoped_ptr<AthenaStartPageView> view_;
105
106 private:
107  AthenaTestViewDelegate view_delegate_;
108
109  DISALLOW_COPY_AND_ASSIGN(AthenaStartPageViewTest);
110};
111
112TEST_F(AthenaStartPageViewTest, BasicLayout) {
113  // BOTTOM state. logo is invisible. icons, search box, and controls are
114  // arranged horizontally.
115  EXPECT_FALSE(IsLogoVisible());
116
117  // Three components are aligned at the middle point.
118  EXPECT_NEAR(GetIconsBounds().CenterPoint().y(),
119              GetControlBounds().CenterPoint().y(),
120              1);
121  EXPECT_NEAR(GetIconsBounds().CenterPoint().y(),
122              GetSearchBoxBounds().CenterPoint().y(),
123              1);
124  EXPECT_NEAR(GetControlBounds().CenterPoint().y(),
125              GetSearchBoxBounds().CenterPoint().y(),
126              1);
127
128  // Horizonttaly aligned in the order of icons, search_box, and controls.
129  EXPECT_LE(GetIconsBounds().right(), GetSearchBoxBounds().x());
130  EXPECT_LE(GetSearchBoxBounds().right(), GetControlBounds().x());
131  EXPECT_LE(0, GetIconsBounds().y());
132
133  // Search box should appear in the middle.
134  EXPECT_NEAR(GetSearchBoxBounds().CenterPoint().x(),
135              view_->bounds().CenterPoint().x(),
136              1);
137
138  // Should fit inside of the home card height.
139  EXPECT_GE(kHomeCardHeight, GetIconsBounds().height());
140  EXPECT_GE(kHomeCardHeight, GetSearchBoxBounds().height());
141  EXPECT_GE(kHomeCardHeight, GetControlBounds().height());
142  EXPECT_EQ(GetSearchBoxPreferredSize().ToString(),
143            GetSearchBoxBounds().size().ToString());
144
145  // CENTERED state. logo is visible. search box appears below the logo,
146  // icons and controls are arranged horizontally and below the search box.
147  view_->SetLayoutState(1.0f);
148  EXPECT_TRUE(IsLogoVisible());
149  EXPECT_NEAR(GetLogoBounds().x() + GetLogoBounds().width() / 2,
150              GetSearchBoxBounds().x() + GetSearchBoxBounds().width() / 2,
151              1);
152  EXPECT_LE(GetLogoBounds().bottom(), GetSearchBoxBounds().y());
153  EXPECT_EQ(GetIconsBounds().y(), GetControlBounds().y());
154  EXPECT_LE(GetIconsBounds().right(), GetControlBounds().x());
155  EXPECT_LE(GetSearchBoxBounds().bottom(), GetIconsBounds().y());
156}
157
158TEST_F(AthenaStartPageViewTest, NarrowLayout) {
159  SetSize(gfx::Size(800, 1280));
160
161  // BOTTOM state. Similar to BasicLayout.
162  EXPECT_FALSE(IsLogoVisible());
163  // Three components are aligned at the middle point.
164  EXPECT_NEAR(GetIconsBounds().CenterPoint().y(),
165              GetControlBounds().CenterPoint().y(),
166              1);
167  EXPECT_NEAR(GetIconsBounds().CenterPoint().y(),
168              GetSearchBoxBounds().CenterPoint().y(),
169              1);
170  EXPECT_NEAR(GetControlBounds().CenterPoint().y(),
171              GetSearchBoxBounds().CenterPoint().y(),
172              1);
173
174  // Horizonttaly aligned in the order of icons, search_box, and controls.
175  EXPECT_LE(GetIconsBounds().right(), GetSearchBoxBounds().x());
176  EXPECT_LE(GetSearchBoxBounds().right(), GetControlBounds().x());
177  EXPECT_LE(0, GetIconsBounds().y());
178
179  // Search box should appear in the middle.
180  EXPECT_NEAR(GetSearchBoxBounds().CenterPoint().x(),
181              view_->bounds().CenterPoint().x(),
182              1);
183
184  // Should fit inside of the home card height.
185  EXPECT_GE(kHomeCardHeight, GetIconsBounds().height());
186  EXPECT_GE(kHomeCardHeight, GetSearchBoxBounds().height());
187  EXPECT_GE(kHomeCardHeight, GetControlBounds().height());
188
189  // Search box is narrower because of the size is too narrow.
190  EXPECT_GT(GetSearchBoxPreferredSize().width(), GetSearchBoxBounds().width());
191  EXPECT_EQ(GetSearchBoxPreferredSize().height(),
192            GetSearchBoxBounds().height());
193
194  // CENTERED state. Search box should be back to the preferred size.
195  view_->SetLayoutState(1.0f);
196  EXPECT_EQ(GetSearchBoxPreferredSize().ToString(),
197            GetSearchBoxBounds().size().ToString());
198
199  // Back to BOTTOM state, the search box shrinks again.
200  view_->SetLayoutState(0.0f);
201  EXPECT_GT(GetSearchBoxPreferredSize().width(), GetSearchBoxBounds().width());
202
203  // Then set back to the original size, now the size is wide enough so the
204  // search box bounds becomes as preferred.
205  SetSize(gfx::Size(1280, 800));
206  EXPECT_EQ(GetSearchBoxPreferredSize().ToString(),
207            GetSearchBoxBounds().size().ToString());
208}
209
210TEST_F(AthenaStartPageViewTest, SearchBox) {
211  view_->SetLayoutState(1.0f);
212  EXPECT_TRUE(IsLogoVisible());
213
214  const gfx::Rect base_search_box_bounds = GetSearchBoxBounds();
215
216  const base::string16 query = base::UTF8ToUTF16("test");
217  SetSearchQuery(query);
218
219  EXPECT_FALSE(IsLogoVisible());
220  EXPECT_GT(base_search_box_bounds.y(), GetSearchBoxBounds().y());
221  EXPECT_EQ(query, GetVisibleQuery());
222
223  SetSearchQuery(base::string16());
224  EXPECT_TRUE(IsLogoVisible());
225  EXPECT_EQ(base_search_box_bounds.ToString(), GetSearchBoxBounds().ToString());
226  EXPECT_TRUE(GetVisibleQuery().empty());
227}
228
229}  // namespace athena
230