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 18namespace app_list { 19namespace test { 20 21namespace { 22int kDefaultSearchItems = 5; 23} // namespace 24 25class SearchResultListViewTest : public views::ViewsTestBase, 26 public SearchResultListViewDelegate { 27 public: 28 SearchResultListViewTest() {} 29 virtual ~SearchResultListViewTest() {} 30 31 // Overridden from testing::Test: 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: 40 SearchResultListView* view() { return view_.get(); } 41 42 AppListModel::SearchResults* GetResults() { 43 return view_delegate_.GetModel()->results(); 44 } 45 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 51 base::TimeDelta GetAutoLaunchTimeout() { 52 return view_delegate_.GetAutoLaunchTimeout(); 53 } 54 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 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 70 int GetResultCount() { return view_->last_visible_index_ + 1; } 71 72 int GetSelectedIndex() { 73 return view_->selected_index_; 74 } 75 76 void ResetSelectedIndex() { 77 view_->SetSelectedIndex(0); 78 } 79 80 void AddTestResultAtIndex(int index) { 81 GetResults()->Add(new SearchResult()); 82 } 83 84 void DeleteResultAt(int index) { GetResults()->DeleteAt(index); } 85 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 91 bool IsAutoLaunching() { 92 return view_->auto_launch_animation_; 93 } 94 95 void ForceAutoLaunch() { 96 view_->ForceAutoLaunchForTest(); 97 } 98 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 109 ProgressBarView* GetProgressBarAt(size_t index) { 110 return view()->GetResultViewAt(index)->progress_bar_; 111 } 112 113 private: 114 virtual void OnResultInstalled(SearchResult* result) OVERRIDE {} 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 123TEST_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 160TEST_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 175TEST_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 196TEST_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(). 219TEST_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