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.
5 #include "ui/app_list/app_list_model.h"
9 #include "base/strings/utf_string_conversions.h"
10 #include "testing/gtest/include/gtest/gtest.h"
11 #include "ui/app_list/app_list_folder_item.h"
12 #include "ui/app_list/app_list_item_model.h"
13 #include "ui/app_list/app_list_model_observer.h"
14 #include "ui/app_list/test/app_list_test_model.h"
15 #include "ui/base/models/list_model_observer.h"
21 class TestObserver
: public AppListModelObserver
,
22 public AppListItemListObserver
{
25 : status_changed_count_(0),
26 users_changed_count_(0),
27 signin_changed_count_(0),
32 virtual ~TestObserver() {
35 // AppListModelObserver
36 virtual void OnAppListModelStatusChanged() OVERRIDE
{
37 ++status_changed_count_
;
40 virtual void OnAppListModelUsersChanged() OVERRIDE
{
41 ++users_changed_count_
;
44 virtual void OnAppListModelSigninStatusChanged() OVERRIDE
{
45 ++signin_changed_count_
;
48 // AppListItemListObserver
49 virtual void OnListItemAdded(size_t index
, AppListItemModel
* item
) OVERRIDE
{
53 virtual void OnListItemRemoved(size_t index
,
54 AppListItemModel
* item
) OVERRIDE
{
58 virtual void OnListItemMoved(size_t from_index
,
60 AppListItemModel
* item
) OVERRIDE
{
64 int status_changed_count() const { return status_changed_count_
; }
65 int users_changed_count() const { return users_changed_count_
; }
66 int signin_changed_count() const { return signin_changed_count_
; }
67 size_t items_added() { return items_added_
; }
68 size_t items_removed() { return items_removed_
; }
69 size_t items_moved() { return items_moved_
; }
72 status_changed_count_
= 0;
73 users_changed_count_
= 0;
74 signin_changed_count_
= 0;
81 int status_changed_count_
;
82 int users_changed_count_
;
83 int signin_changed_count_
;
85 size_t items_removed_
;
88 DISALLOW_COPY_AND_ASSIGN(TestObserver
);
93 class AppListModelTest
: public testing::Test
{
96 virtual ~AppListModelTest() {}
98 // testing::Test overrides:
99 virtual void SetUp() OVERRIDE
{
100 model_
.AddObserver(&observer_
);
101 model_
.item_list()->AddObserver(&observer_
);
103 virtual void TearDown() OVERRIDE
{
104 model_
.RemoveObserver(&observer_
);
105 model_
.item_list()->RemoveObserver(&observer_
);
109 bool ItemObservedByFolder(AppListFolderItem
* folder
,
110 AppListItemModel
* item
) {
111 return item
->observers_
.HasObserver(folder
);
114 test::AppListTestModel model_
;
115 TestObserver observer_
;
118 DISALLOW_COPY_AND_ASSIGN(AppListModelTest
);
121 TEST_F(AppListModelTest
, SetStatus
) {
122 EXPECT_EQ(AppListModel::STATUS_NORMAL
, model_
.status());
123 model_
.SetStatus(AppListModel::STATUS_SYNCING
);
124 EXPECT_EQ(1, observer_
.status_changed_count());
125 EXPECT_EQ(AppListModel::STATUS_SYNCING
, model_
.status());
126 model_
.SetStatus(AppListModel::STATUS_NORMAL
);
127 EXPECT_EQ(2, observer_
.status_changed_count());
128 // Set the same status, no change is expected.
129 model_
.SetStatus(AppListModel::STATUS_NORMAL
);
130 EXPECT_EQ(2, observer_
.status_changed_count());
133 TEST_F(AppListModelTest
, SetUsers
) {
134 EXPECT_EQ(0u, model_
.users().size());
135 AppListModel::Users users
;
136 users
.push_back(AppListModel::User());
137 users
[0].name
= UTF8ToUTF16("test");
138 model_
.SetUsers(users
);
139 EXPECT_EQ(1, observer_
.users_changed_count());
140 ASSERT_EQ(1u, model_
.users().size());
141 EXPECT_EQ(UTF8ToUTF16("test"), model_
.users()[0].name
);
144 TEST_F(AppListModelTest
, SetSignedIn
) {
145 EXPECT_TRUE(model_
.signed_in());
146 model_
.SetSignedIn(false);
147 EXPECT_EQ(1, observer_
.signin_changed_count());
148 EXPECT_FALSE(model_
.signed_in());
149 model_
.SetSignedIn(true);
150 EXPECT_EQ(2, observer_
.signin_changed_count());
151 EXPECT_TRUE(model_
.signed_in());
152 // Set the same signin state, no change is expected.
153 model_
.SetSignedIn(true);
154 EXPECT_EQ(2, observer_
.signin_changed_count());
157 TEST_F(AppListModelTest
, AppsObserver
) {
158 const size_t num_apps
= 2;
159 model_
.PopulateApps(num_apps
);
160 EXPECT_EQ(num_apps
, observer_
.items_added());
163 TEST_F(AppListModelTest
, ModelGetItem
) {
164 const size_t num_apps
= 2;
165 model_
.PopulateApps(num_apps
);
166 AppListItemModel
* item0
= model_
.item_list()->item_at(0);
168 EXPECT_EQ(model_
.GetItemName(0), item0
->id());
169 AppListItemModel
* item1
= model_
.item_list()->item_at(1);
171 EXPECT_EQ(model_
.GetItemName(1), item1
->id());
174 TEST_F(AppListModelTest
, ModelFindItem
) {
175 const size_t num_apps
= 2;
176 model_
.PopulateApps(num_apps
);
177 std::string item_name0
= model_
.GetItemName(0);
178 AppListItemModel
* item0
= model_
.item_list()->FindItem(item_name0
);
180 EXPECT_EQ(item_name0
, item0
->id());
181 std::string item_name1
= model_
.GetItemName(1);
182 AppListItemModel
* item1
= model_
.item_list()->FindItem(item_name1
);
184 EXPECT_EQ(item_name1
, item1
->id());
187 TEST_F(AppListModelTest
, ModelAddItem
) {
188 const size_t num_apps
= 2;
189 model_
.PopulateApps(num_apps
);
190 // Adding another item will add it to the end.
191 model_
.CreateAndAddItem("Added Item 1");
192 ASSERT_EQ(num_apps
+ 1, model_
.item_list()->item_count());
193 EXPECT_EQ("Added Item 1", model_
.item_list()->item_at(num_apps
)->id());
194 // Add an item between items 0 and 1.
195 app_list::AppListItemModel
* item0
= model_
.item_list()->item_at(0);
197 app_list::AppListItemModel
* item1
= model_
.item_list()->item_at(1);
199 app_list::AppListItemModel
* item2
=
200 model_
.CreateItem("Added Item 2", "Added Item 2");
201 item2
->set_position(item0
->position().CreateBetween(item1
->position()));
202 model_
.item_list()->AddItem(item2
);
203 EXPECT_EQ(num_apps
+ 2, model_
.item_list()->item_count());
204 EXPECT_EQ("Added Item 2", model_
.item_list()->item_at(1)->id());
207 TEST_F(AppListModelTest
, ModelMoveItem
) {
208 const size_t num_apps
= 3;
209 model_
.PopulateApps(num_apps
);
210 // Adding another item will add it to the end.
211 model_
.CreateAndAddItem("Inserted Item");
212 ASSERT_EQ(num_apps
+ 1, model_
.item_list()->item_count());
213 // Move it to the position 1.
214 model_
.item_list()->MoveItem(num_apps
, 1);
215 AppListItemModel
* item
= model_
.item_list()->item_at(1);
217 EXPECT_EQ("Inserted Item", item
->id());
220 TEST_F(AppListModelTest
, ModelRemoveItem
) {
221 const size_t num_apps
= 4;
222 model_
.PopulateApps(num_apps
);
223 // Remove an item in the middle.
224 model_
.item_list()->DeleteItem(model_
.GetItemName(1));
225 EXPECT_EQ(num_apps
- 1, model_
.item_list()->item_count());
226 EXPECT_EQ(1u, observer_
.items_removed());
227 // Remove the first item in the list.
228 model_
.item_list()->DeleteItem(model_
.GetItemName(0));
229 EXPECT_EQ(num_apps
- 2, model_
.item_list()->item_count());
230 EXPECT_EQ(2u, observer_
.items_removed());
231 // Remove the last item in the list.
232 model_
.item_list()->DeleteItem(model_
.GetItemName(num_apps
- 1));
233 EXPECT_EQ(num_apps
- 3, model_
.item_list()->item_count());
234 EXPECT_EQ(3u, observer_
.items_removed());
235 // Ensure that the first item is the expected one
236 AppListItemModel
* item0
= model_
.item_list()->item_at(0);
238 EXPECT_EQ(model_
.GetItemName(2), item0
->id());
241 TEST_F(AppListModelTest
, ModelRemoveItemByType
) {
242 const size_t num_apps
= 4;
243 model_
.PopulateApps(num_apps
);
244 model_
.item_list()->AddItem(new AppListFolderItem("folder1"));
245 model_
.item_list()->AddItem(new AppListFolderItem("folder2"));
246 model_
.item_list()->DeleteItemsByType(test::AppListTestModel::kAppType
);
247 EXPECT_EQ(num_apps
, observer_
.items_removed());
248 EXPECT_EQ(2u, model_
.item_list()->item_count());
249 model_
.item_list()->DeleteItemsByType(AppListFolderItem::kAppType
);
250 EXPECT_EQ(num_apps
+ 2, observer_
.items_removed());
251 EXPECT_EQ(0u, model_
.item_list()->item_count());
253 observer_
.ResetCounts();
254 model_
.PopulateApps(num_apps
);
255 model_
.item_list()->AddItem(new AppListFolderItem("folder1"));
256 model_
.item_list()->AddItem(new AppListFolderItem("folder2"));
257 model_
.item_list()->DeleteItemsByType(NULL
/* all items */);
258 EXPECT_EQ(num_apps
+ 2, observer_
.items_removed());
259 EXPECT_EQ(0u, model_
.item_list()->item_count());
262 TEST_F(AppListModelTest
, AppOrder
) {
263 const size_t num_apps
= 5;
264 model_
.PopulateApps(num_apps
);
265 // Ensure order is preserved.
266 for (size_t i
= 1; i
< num_apps
; ++i
) {
267 EXPECT_TRUE(model_
.item_list()->item_at(i
)->position().GreaterThan(
268 model_
.item_list()->item_at(i
- 1)->position()));
271 model_
.item_list()->MoveItem(num_apps
- 1, 1);
272 // Ensure order is preserved.
273 for (size_t i
= 1; i
< num_apps
; ++i
) {
274 EXPECT_TRUE(model_
.item_list()->item_at(i
)->position().GreaterThan(
275 model_
.item_list()->item_at(i
- 1)->position()));
279 TEST_F(AppListModelTest
, FolderItem
) {
280 AppListFolderItem
* folder
= new AppListFolderItem("folder1");
281 const size_t num_folder_apps
= 8;
282 const size_t num_observed_apps
= 4;
283 for (int i
= 0; static_cast<size_t>(i
) < num_folder_apps
; ++i
) {
284 std::string name
= model_
.GetItemName(i
);
285 folder
->item_list()->AddItem(model_
.CreateItem(name
, name
));
287 // Check that items 0 and 3 are observed.
288 EXPECT_TRUE(ItemObservedByFolder(folder
, folder
->item_list()->item_at(0)));
289 EXPECT_TRUE(ItemObservedByFolder(
290 folder
, folder
->item_list()->item_at(num_observed_apps
- 1)));
291 // Check that item 4 is not observed.
292 EXPECT_FALSE(ItemObservedByFolder(
293 folder
, folder
->item_list()->item_at(num_observed_apps
)));
294 folder
->item_list()->MoveItem(num_observed_apps
, 0);
295 // Confirm that everything was moved where expected.
296 EXPECT_EQ(model_
.GetItemName(num_observed_apps
),
297 folder
->item_list()->item_at(0)->id());
298 EXPECT_EQ(model_
.GetItemName(0),
299 folder
->item_list()->item_at(1)->id());
300 EXPECT_EQ(model_
.GetItemName(num_observed_apps
- 1),
301 folder
->item_list()->item_at(num_observed_apps
)->id());
302 // Check that items 0 and 3 are observed.
303 EXPECT_TRUE(ItemObservedByFolder(folder
, folder
->item_list()->item_at(0)));
304 EXPECT_TRUE(ItemObservedByFolder(
305 folder
, folder
->item_list()->item_at(num_observed_apps
- 1)));
306 // Check that item 4 is not observed.
307 EXPECT_FALSE(ItemObservedByFolder(
308 folder
, folder
->item_list()->item_at(num_observed_apps
)));
311 } // namespace app_list