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 "ui/app_list/views/search_result_list_view.h"
6
7 #include <map>
8
9 #include "base/strings/utf_string_conversions.h"
10 #include "ui/app_list/app_list_model.h"
11 #include "ui/app_list/search_result.h"
12 #include "ui/app_list/test/app_list_test_view_delegate.h"
13 #include "ui/app_list/views/progress_bar_view.h"
14 #include "ui/app_list/views/search_result_list_view_delegate.h"
15 #include "ui/app_list/views/search_result_view.h"
16 #include "ui/views/test/views_test_base.h"
17
18 namespace app_list {
19 namespace test {
20
21 namespace {
22 int kDefaultSearchItems = 5;
23 } // namespace
24
25 class SearchResultListViewTest : public views::ViewsTestBase,
26 public SearchResultListViewDelegate {
27 public:
SearchResultListViewTest()28 SearchResultListViewTest() {}
~SearchResultListViewTest()29 virtual ~SearchResultListViewTest() {}
30
31 // Overridden from testing::Test:
SetUp()32 virtual void SetUp() OVERRIDE {
33 views::ViewsTestBase::SetUp();
34 view_.reset(new SearchResultListView(this, &view_delegate_));
35 view_->SetResults(view_delegate_.GetModel()->results());
36 view_->SetSelectedIndex(0);
37 }
38
39 protected:
view()40 SearchResultListView* view() { return view_.get(); }
41
GetResults()42 AppListModel::SearchResults* GetResults() {
43 return view_delegate_.GetModel()->results();
44 }
45
SetLongAutoLaunchTimeout()46 void SetLongAutoLaunchTimeout() {
47 // Sets a long timeout that lasts longer than the test run.
48 view_delegate_.set_auto_launch_timeout(base::TimeDelta::FromDays(1));
49 }
50
GetAutoLaunchTimeout()51 base::TimeDelta GetAutoLaunchTimeout() {
52 return view_delegate_.GetAutoLaunchTimeout();
53 }
54
SetUpSearchResults()55 void SetUpSearchResults() {
56 AppListModel::SearchResults* results = GetResults();
57 for (int i = 0; i < kDefaultSearchItems; ++i)
58 results->Add(new SearchResult());
59
60 // Adding results will schedule Update().
61 RunPendingMessages();
62 }
63
GetOpenResultCountAndReset(int ranking)64 int GetOpenResultCountAndReset(int ranking) {
65 int result = view_delegate_.open_search_result_counts()[ranking];
66 view_delegate_.open_search_result_counts().clear();
67 return result;
68 }
69
GetResultCount()70 int GetResultCount() { return view_->last_visible_index_ + 1; }
71
GetSelectedIndex()72 int GetSelectedIndex() {
73 return view_->selected_index_;
74 }
75
ResetSelectedIndex()76 void ResetSelectedIndex() {
77 view_->SetSelectedIndex(0);
78 }
79
AddTestResultAtIndex(int index)80 void AddTestResultAtIndex(int index) {
81 GetResults()->Add(new SearchResult());
82 }
83
DeleteResultAt(int index)84 void DeleteResultAt(int index) { GetResults()->DeleteAt(index); }
85
KeyPress(ui::KeyboardCode key_code)86 bool KeyPress(ui::KeyboardCode key_code) {
87 ui::KeyEvent event(ui::ET_KEY_PRESSED, key_code, ui::EF_NONE);
88 return view_->OnKeyPressed(event);
89 }
90
IsAutoLaunching()91 bool IsAutoLaunching() {
92 return view_->auto_launch_animation_;
93 }
94
ForceAutoLaunch()95 void ForceAutoLaunch() {
96 view_->ForceAutoLaunchForTest();
97 }
98
ExpectConsistent()99 void ExpectConsistent() {
100 // Adding results will schedule Update().
101 RunPendingMessages();
102
103 AppListModel::SearchResults* results = GetResults();
104 for (size_t i = 0; i < results->item_count(); ++i) {
105 EXPECT_EQ(results->GetItemAt(i), view_->GetResultViewAt(i)->result());
106 }
107 }
108
GetProgressBarAt(size_t index)109 ProgressBarView* GetProgressBarAt(size_t index) {
110 return view()->GetResultViewAt(index)->progress_bar_;
111 }
112
113 private:
OnResultInstalled(SearchResult * result)114 virtual void OnResultInstalled(SearchResult* result) OVERRIDE {}
OnResultUninstalled(SearchResult * result)115 virtual void OnResultUninstalled(SearchResult* result) OVERRIDE {}
116
117 AppListTestViewDelegate view_delegate_;
118 scoped_ptr<SearchResultListView> view_;
119
120 DISALLOW_COPY_AND_ASSIGN(SearchResultListViewTest);
121 };
122
TEST_F(SearchResultListViewTest,Basic)123 TEST_F(SearchResultListViewTest, Basic) {
124 SetUpSearchResults();
125
126 const int results = GetResultCount();
127 EXPECT_EQ(kDefaultSearchItems, results);
128 EXPECT_EQ(0, GetSelectedIndex());
129 EXPECT_FALSE(IsAutoLaunching());
130
131 EXPECT_TRUE(KeyPress(ui::VKEY_RETURN));
132 EXPECT_EQ(1, GetOpenResultCountAndReset(0));
133
134 for (int i = 1; i < results; ++i) {
135 EXPECT_TRUE(KeyPress(ui::VKEY_DOWN));
136 EXPECT_EQ(i, GetSelectedIndex());
137 }
138 // Doesn't rotate.
139 EXPECT_TRUE(KeyPress(ui::VKEY_DOWN));
140 EXPECT_EQ(results - 1, GetSelectedIndex());
141
142 for (int i = 1; i < results; ++i) {
143 EXPECT_TRUE(KeyPress(ui::VKEY_UP));
144 EXPECT_EQ(results - i - 1, GetSelectedIndex());
145 }
146 // Doesn't rotate.
147 EXPECT_TRUE(KeyPress(ui::VKEY_UP));
148 EXPECT_EQ(0, GetSelectedIndex());
149 ResetSelectedIndex();
150
151 for (int i = 1; i < results; ++i) {
152 EXPECT_TRUE(KeyPress(ui::VKEY_TAB));
153 EXPECT_EQ(i, GetSelectedIndex());
154 }
155 // Doesn't rotate.
156 EXPECT_TRUE(KeyPress(ui::VKEY_TAB));
157 EXPECT_EQ(results - 1, GetSelectedIndex());
158 }
159
TEST_F(SearchResultListViewTest,AutoLaunch)160 TEST_F(SearchResultListViewTest, AutoLaunch) {
161 SetLongAutoLaunchTimeout();
162 SetUpSearchResults();
163
164 EXPECT_TRUE(IsAutoLaunching());
165 ForceAutoLaunch();
166
167 EXPECT_FALSE(IsAutoLaunching());
168 EXPECT_EQ(1, GetOpenResultCountAndReset(0));
169
170 // The timeout has to be cleared after the auto-launch, to prevent opening
171 // the search result twice. See the comment in AnimationEnded().
172 EXPECT_EQ(base::TimeDelta(), GetAutoLaunchTimeout());
173 }
174
TEST_F(SearchResultListViewTest,CancelAutoLaunch)175 TEST_F(SearchResultListViewTest, CancelAutoLaunch) {
176 SetLongAutoLaunchTimeout();
177 SetUpSearchResults();
178
179 EXPECT_TRUE(IsAutoLaunching());
180
181 EXPECT_TRUE(KeyPress(ui::VKEY_DOWN));
182 EXPECT_FALSE(IsAutoLaunching());
183
184 SetLongAutoLaunchTimeout();
185 view()->UpdateAutoLaunchState();
186 EXPECT_TRUE(IsAutoLaunching());
187
188 view()->SetVisible(false);
189 EXPECT_FALSE(IsAutoLaunching());
190
191 SetLongAutoLaunchTimeout();
192 view()->SetVisible(true);
193 EXPECT_TRUE(IsAutoLaunching());
194 }
195
TEST_F(SearchResultListViewTest,ModelObservers)196 TEST_F(SearchResultListViewTest, ModelObservers) {
197 SetUpSearchResults();
198 ExpectConsistent();
199
200 // Insert at start.
201 AddTestResultAtIndex(0);
202 ExpectConsistent();
203
204 // Remove from end.
205 DeleteResultAt(kDefaultSearchItems);
206 ExpectConsistent();
207
208 // Insert at end.
209 AddTestResultAtIndex(kDefaultSearchItems);
210 ExpectConsistent();
211
212 // Delete from start.
213 DeleteResultAt(0);
214 ExpectConsistent();
215 }
216
217 // Regression test for http://crbug.com/402859 to ensure ProgressBar is
218 // initialized properly in SearchResultListView::SetResult().
TEST_F(SearchResultListViewTest,ProgressBar)219 TEST_F(SearchResultListViewTest, ProgressBar) {
220 SetUpSearchResults();
221
222 GetResults()->GetItemAt(0)->SetIsInstalling(true);
223 EXPECT_EQ(0.0f, GetProgressBarAt(0)->current_value());
224 GetResults()->GetItemAt(0)->SetPercentDownloaded(10);
225
226 DeleteResultAt(0);
227 RunPendingMessages();
228 EXPECT_EQ(0.0f, GetProgressBarAt(0)->current_value());
229 }
230
231 } // namespace test
232 } // namespace app_list
233