Blink roll 171798:171837
[chromium-blink-merge.git] / ui / app_list / app_list_model_unittest.cc
blob3d7619e76a78a153d09ae266aa305276f7035db5
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"
7 #include <map>
8 #include <string>
10 #include "base/command_line.h"
11 #include "base/strings/utf_string_conversions.h"
12 #include "testing/gtest/include/gtest/gtest.h"
13 #include "ui/app_list/app_list_folder_item.h"
14 #include "ui/app_list/app_list_item.h"
15 #include "ui/app_list/app_list_model_observer.h"
16 #include "ui/app_list/app_list_switches.h"
17 #include "ui/app_list/test/app_list_test_model.h"
18 #include "ui/base/models/list_model_observer.h"
20 namespace app_list {
22 namespace {
24 class TestObserver : public AppListModelObserver {
25 public:
26 TestObserver()
27 : status_changed_count_(0),
28 items_added_(0),
29 items_removed_(0),
30 items_updated_(0) {
32 virtual ~TestObserver() {
35 // AppListModelObserver
36 virtual void OnAppListModelStatusChanged() OVERRIDE {
37 ++status_changed_count_;
40 virtual void OnAppListItemAdded(AppListItem* item) OVERRIDE {
41 items_added_++;
44 virtual void OnAppListItemWillBeDeleted(AppListItem* item) OVERRIDE {
45 items_removed_++;
48 virtual void OnAppListItemUpdated(AppListItem* item) OVERRIDE {
49 items_updated_++;
52 int status_changed_count() const { return status_changed_count_; }
53 size_t items_added() { return items_added_; }
54 size_t items_removed() { return items_removed_; }
55 size_t items_updated() { return items_updated_; }
57 void ResetCounts() {
58 status_changed_count_ = 0;
59 items_added_ = 0;
60 items_removed_ = 0;
61 items_updated_ = 0;
64 private:
65 int status_changed_count_;
66 size_t items_added_;
67 size_t items_removed_;
68 size_t items_updated_;
70 DISALLOW_COPY_AND_ASSIGN(TestObserver);
73 } // namespace
75 class AppListModelTest : public testing::Test {
76 public:
77 AppListModelTest() {}
78 virtual ~AppListModelTest() {}
80 // testing::Test overrides:
81 virtual void SetUp() OVERRIDE {
82 model_.AddObserver(&observer_);
84 virtual void TearDown() OVERRIDE {
85 model_.RemoveObserver(&observer_);
88 protected:
89 bool ItemObservedByFolder(AppListFolderItem* folder,
90 AppListItem* item) {
91 return item->observers_.HasObserver(folder);
94 std::string GetItemListContents(AppListItemList* item_list) {
95 std::string s;
96 for (size_t i = 0; i < item_list->item_count(); ++i) {
97 if (i != 0)
98 s += ",";
99 s += item_list->item_at(i)->id();
101 return s;
104 std::string GetModelContents() {
105 return GetItemListContents(model_.top_level_item_list());
108 test::AppListTestModel model_;
109 TestObserver observer_;
111 private:
112 DISALLOW_COPY_AND_ASSIGN(AppListModelTest);
115 TEST_F(AppListModelTest, SetStatus) {
116 EXPECT_EQ(AppListModel::STATUS_NORMAL, model_.status());
117 model_.SetStatus(AppListModel::STATUS_SYNCING);
118 EXPECT_EQ(1, observer_.status_changed_count());
119 EXPECT_EQ(AppListModel::STATUS_SYNCING, model_.status());
120 model_.SetStatus(AppListModel::STATUS_NORMAL);
121 EXPECT_EQ(2, observer_.status_changed_count());
122 // Set the same status, no change is expected.
123 model_.SetStatus(AppListModel::STATUS_NORMAL);
124 EXPECT_EQ(2, observer_.status_changed_count());
127 TEST_F(AppListModelTest, AppsObserver) {
128 const size_t num_apps = 2;
129 model_.PopulateApps(num_apps);
130 EXPECT_EQ(num_apps, observer_.items_added());
133 TEST_F(AppListModelTest, ModelGetItem) {
134 const size_t num_apps = 2;
135 model_.PopulateApps(num_apps);
136 AppListItem* item0 = model_.top_level_item_list()->item_at(0);
137 ASSERT_TRUE(item0);
138 EXPECT_EQ(model_.GetItemName(0), item0->id());
139 AppListItem* item1 = model_.top_level_item_list()->item_at(1);
140 ASSERT_TRUE(item1);
141 EXPECT_EQ(model_.GetItemName(1), item1->id());
144 TEST_F(AppListModelTest, ModelFindItem) {
145 const size_t num_apps = 2;
146 model_.PopulateApps(num_apps);
147 std::string item_name0 = model_.GetItemName(0);
148 AppListItem* item0 = model_.FindItem(item_name0);
149 ASSERT_TRUE(item0);
150 EXPECT_EQ(item_name0, item0->id());
151 std::string item_name1 = model_.GetItemName(1);
152 AppListItem* item1 = model_.FindItem(item_name1);
153 ASSERT_TRUE(item1);
154 EXPECT_EQ(item_name1, item1->id());
157 TEST_F(AppListModelTest, SetItemPosition) {
158 const size_t num_apps = 2;
159 model_.PopulateApps(num_apps);
160 // Adding another item will add it to the end.
161 model_.CreateAndAddItem("Added Item 1");
162 ASSERT_EQ(num_apps + 1, model_.top_level_item_list()->item_count());
163 EXPECT_EQ("Added Item 1",
164 model_.top_level_item_list()->item_at(num_apps)->id());
165 // Add an item between items 0 and 1.
166 AppListItem* item0 = model_.top_level_item_list()->item_at(0);
167 ASSERT_TRUE(item0);
168 AppListItem* item1 = model_.top_level_item_list()->item_at(1);
169 ASSERT_TRUE(item1);
170 AppListItem* item2 = model_.CreateItem("Added Item 2");
171 model_.AddItem(item2);
172 EXPECT_EQ("Item 0,Item 1,Added Item 1,Added Item 2", GetModelContents());
173 model_.SetItemPosition(
174 item2, item0->position().CreateBetween(item1->position()));
175 EXPECT_EQ(num_apps + 2, model_.top_level_item_list()->item_count());
176 EXPECT_EQ(num_apps + 2, observer_.items_added());
177 EXPECT_EQ("Item 0,Added Item 2,Item 1,Added Item 1", GetModelContents());
180 TEST_F(AppListModelTest, ModelMoveItem) {
181 const size_t num_apps = 3;
182 model_.PopulateApps(num_apps);
183 // Adding another item will add it to the end.
184 model_.CreateAndAddItem("Inserted Item");
185 ASSERT_EQ(num_apps + 1, model_.top_level_item_list()->item_count());
186 // Move it to the position 1.
187 observer_.ResetCounts();
188 model_.top_level_item_list()->MoveItem(num_apps, 1);
189 EXPECT_EQ(1u, observer_.items_updated());
190 EXPECT_EQ("Item 0,Inserted Item,Item 1,Item 2", GetModelContents());
193 TEST_F(AppListModelTest, ModelRemoveItem) {
194 const size_t num_apps = 4;
195 model_.PopulateApps(num_apps);
196 // Remove an item in the middle.
197 model_.DeleteItem(model_.GetItemName(1));
198 EXPECT_EQ(num_apps - 1, model_.top_level_item_list()->item_count());
199 EXPECT_EQ(1u, observer_.items_removed());
200 EXPECT_EQ("Item 0,Item 2,Item 3", GetModelContents());
201 // Remove the first item in the list.
202 model_.DeleteItem(model_.GetItemName(0));
203 EXPECT_EQ(num_apps - 2, model_.top_level_item_list()->item_count());
204 EXPECT_EQ(2u, observer_.items_removed());
205 EXPECT_EQ("Item 2,Item 3", GetModelContents());
206 // Remove the last item in the list.
207 model_.DeleteItem(model_.GetItemName(num_apps - 1));
208 EXPECT_EQ(num_apps - 3, model_.top_level_item_list()->item_count());
209 EXPECT_EQ(3u, observer_.items_removed());
210 EXPECT_EQ("Item 2", GetModelContents());
213 TEST_F(AppListModelTest, AppOrder) {
214 const size_t num_apps = 5;
215 model_.PopulateApps(num_apps);
216 // Ensure order is preserved.
217 for (size_t i = 1; i < num_apps; ++i) {
218 EXPECT_TRUE(
219 model_.top_level_item_list()->item_at(i)->position().GreaterThan(
220 model_.top_level_item_list()->item_at(i - 1)->position()));
222 // Move an app
223 model_.top_level_item_list()->MoveItem(num_apps - 1, 1);
224 // Ensure order is preserved.
225 for (size_t i = 1; i < num_apps; ++i) {
226 EXPECT_TRUE(
227 model_.top_level_item_list()->item_at(i)->position().GreaterThan(
228 model_.top_level_item_list()->item_at(i - 1)->position()));
232 class AppListModelFolderTest : public AppListModelTest {
233 public:
234 AppListModelFolderTest() {}
235 virtual ~AppListModelFolderTest() {}
237 // testing::Test overrides:
238 virtual void SetUp() OVERRIDE {
239 AppListModelTest::SetUp();
241 virtual void TearDown() OVERRIDE {
242 AppListModelTest::TearDown();
245 private:
246 DISALLOW_COPY_AND_ASSIGN(AppListModelFolderTest);
249 TEST_F(AppListModelFolderTest, FolderItem) {
250 AppListFolderItem* folder =
251 new AppListFolderItem("folder1", AppListFolderItem::FOLDER_TYPE_NORMAL);
252 const size_t num_folder_apps = 8;
253 const size_t num_observed_apps = 4;
254 model_.AddItem(folder);
255 for (int i = 0; static_cast<size_t>(i) < num_folder_apps; ++i) {
256 std::string name = model_.GetItemName(i);
257 model_.AddItemToFolder(model_.CreateItem(name), folder->id());
259 ASSERT_EQ(num_folder_apps, folder->item_list()->item_count());
260 // Check that items 0 and 3 are observed.
261 EXPECT_TRUE(ItemObservedByFolder(
262 folder, folder->item_list()->item_at(0)));
263 EXPECT_TRUE(ItemObservedByFolder(
264 folder, folder->item_list()->item_at(num_observed_apps - 1)));
265 // Check that item 4 is not observed.
266 EXPECT_FALSE(ItemObservedByFolder(
267 folder, folder->item_list()->item_at(num_observed_apps)));
268 folder->item_list()->MoveItem(num_observed_apps, 0);
269 // Confirm that everything was moved where expected.
270 EXPECT_EQ(model_.GetItemName(num_observed_apps),
271 folder->item_list()->item_at(0)->id());
272 EXPECT_EQ(model_.GetItemName(0),
273 folder->item_list()->item_at(1)->id());
274 EXPECT_EQ(model_.GetItemName(num_observed_apps - 1),
275 folder->item_list()->item_at(num_observed_apps)->id());
276 // Check that items 0 and 3 are observed.
277 EXPECT_TRUE(ItemObservedByFolder(
278 folder, folder->item_list()->item_at(0)));
279 EXPECT_TRUE(ItemObservedByFolder(
280 folder, folder->item_list()->item_at(num_observed_apps - 1)));
281 // Check that item 4 is not observed.
282 EXPECT_FALSE(ItemObservedByFolder(
283 folder, folder->item_list()->item_at(num_observed_apps)));
286 TEST_F(AppListModelFolderTest, MergeItems) {
287 model_.PopulateApps(3);
288 ASSERT_EQ(3u, model_.top_level_item_list()->item_count());
289 AppListItem* item0 = model_.top_level_item_list()->item_at(0);
290 AppListItem* item1 = model_.top_level_item_list()->item_at(1);
291 AppListItem* item2 = model_.top_level_item_list()->item_at(2);
293 // Merge two items.
294 std::string folder1_id = model_.MergeItems(item0->id(), item1->id());
295 ASSERT_EQ(2u, model_.top_level_item_list()->item_count()); // Folder + 1 item
296 AppListFolderItem* folder1_item = model_.FindFolderItem(folder1_id);
297 ASSERT_TRUE(folder1_item);
298 EXPECT_EQ("Item 0,Item 1", GetItemListContents(folder1_item->item_list()));
300 // Merge an item from the new folder into the third item.
301 std::string folder2_id = model_.MergeItems(item2->id(), item1->id());
302 ASSERT_EQ(2u, model_.top_level_item_list()->item_count()); // 2 folders
303 AppListFolderItem* folder2_item = model_.FindFolderItem(folder2_id);
304 EXPECT_EQ("Item 0", GetItemListContents(folder1_item->item_list()));
305 EXPECT_EQ("Item 2,Item 1", GetItemListContents(folder2_item->item_list()));
307 // Merge the remaining item to the new folder, ensure it is added to the end.
308 std::string folder_id = model_.MergeItems(folder2_id, item0->id());
309 EXPECT_EQ(folder2_id, folder_id);
310 EXPECT_EQ("Item 2,Item 1,Item 0",
311 GetItemListContents(folder2_item->item_list()));
313 // The empty folder should be deleted.
314 folder1_item = model_.FindFolderItem(folder1_id);
315 EXPECT_FALSE(folder1_item);
318 TEST_F(AppListModelFolderTest, AddItemToFolder) {
319 AppListFolderItem* folder =
320 new AppListFolderItem("folder1", AppListFolderItem::FOLDER_TYPE_NORMAL);
321 model_.AddItem(folder);
322 AppListItem* item0 = new AppListItem("Item 0");
323 model_.AddItemToFolder(item0, folder->id());
324 ASSERT_EQ(1u, model_.top_level_item_list()->item_count());
325 AppListFolderItem* folder_item = model_.FindFolderItem(folder->id());
326 ASSERT_TRUE(folder_item);
327 ASSERT_EQ(1u, folder_item->item_list()->item_count());
328 EXPECT_EQ(item0, folder_item->item_list()->item_at(0));
329 EXPECT_EQ(folder->id(), item0->folder_id());
332 TEST_F(AppListModelFolderTest, MoveItemToFolder) {
333 AppListFolderItem* folder =
334 new AppListFolderItem("folder1", AppListFolderItem::FOLDER_TYPE_NORMAL);
335 model_.AddItem(folder);
336 AppListItem* item0 = new AppListItem("Item 0");
337 AppListItem* item1 = new AppListItem("Item 1");
338 model_.AddItem(item0);
339 model_.AddItem(item1);
340 ASSERT_EQ(3u, model_.top_level_item_list()->item_count());
341 // Move item0 and item1 to folder.
342 std::string folder_id = folder->id();
343 model_.MoveItemToFolder(item0, folder_id);
344 model_.MoveItemToFolder(item1, folder_id);
345 AppListFolderItem* folder_item = model_.FindFolderItem(folder_id);
346 ASSERT_TRUE(folder_item);
347 EXPECT_EQ(folder_id, item0->folder_id());
348 EXPECT_EQ(folder_id, item1->folder_id());
349 EXPECT_EQ("Item 0,Item 1", GetItemListContents(folder_item->item_list()));
350 // Move item0 out of folder.
351 model_.MoveItemToFolder(item0, "");
352 EXPECT_EQ("", item0->folder_id());
353 folder_item = model_.FindFolderItem(folder_id);
354 ASSERT_TRUE(folder_item);
355 // Move item1 out of folder, folder should be deleted.
356 model_.MoveItemToFolder(item1, "");
357 EXPECT_EQ("", item1->folder_id());
358 folder_item = model_.FindFolderItem(folder_id);
359 EXPECT_FALSE(folder_item);
362 TEST_F(AppListModelFolderTest, MoveItemToFolderAt) {
363 model_.AddItem(new AppListItem("Item 0"));
364 model_.AddItem(new AppListItem("Item 1"));
365 AppListFolderItem* folder1 = static_cast<AppListFolderItem*>(model_.AddItem(
366 new AppListFolderItem("folder1", AppListFolderItem::FOLDER_TYPE_NORMAL)));
367 model_.AddItem(new AppListItem("Item 2"));
368 model_.AddItem(new AppListItem("Item 3"));
369 ASSERT_EQ(5u, model_.top_level_item_list()->item_count());
370 EXPECT_EQ("Item 0,Item 1,folder1,Item 2,Item 3", GetModelContents());
371 // Move Item 1 to folder1, then Item 2 before Item 1.
372 model_.MoveItemToFolderAt(model_.top_level_item_list()->item_at(1),
373 folder1->id(),
374 syncer::StringOrdinal());
375 EXPECT_EQ("Item 0,folder1,Item 2,Item 3", GetModelContents());
376 model_.MoveItemToFolderAt(model_.top_level_item_list()->item_at(2),
377 folder1->id(),
378 folder1->item_list()->item_at(0)->position());
379 EXPECT_EQ("Item 2,Item 1", GetItemListContents(folder1->item_list()));
380 EXPECT_EQ("Item 0,folder1,Item 3", GetModelContents());
381 // Move Item 2 out of folder to before folder.
382 model_.MoveItemToFolderAt(
383 folder1->item_list()->item_at(0), "", folder1->position());
384 EXPECT_EQ("Item 0,Item 2,folder1,Item 3", GetModelContents());
385 // Move remaining folder item, (Item 1) out of folder to folder position.
386 ASSERT_EQ(1u, folder1->item_list()->item_count());
387 model_.MoveItemToFolderAt(
388 folder1->item_list()->item_at(0), "", folder1->position());
389 EXPECT_EQ("Item 0,Item 2,Item 1,Item 3", GetModelContents());
392 TEST_F(AppListModelFolderTest, MoveItemFromFolderToFolder) {
393 AppListFolderItem* folder0 =
394 new AppListFolderItem("folder0", AppListFolderItem::FOLDER_TYPE_NORMAL);
395 AppListFolderItem* folder1 =
396 new AppListFolderItem("folder1", AppListFolderItem::FOLDER_TYPE_NORMAL);
397 model_.AddItem(folder0);
398 model_.AddItem(folder1);
399 EXPECT_EQ("folder0,folder1", GetModelContents());
400 AppListItem* item0 = new AppListItem("Item 0");
401 AppListItem* item1 = new AppListItem("Item 1");
402 model_.AddItemToFolder(item0, folder0->id());
403 model_.AddItemToFolder(item1, folder0->id());
404 EXPECT_EQ(folder0->id(), item0->folder_id());
405 EXPECT_EQ(folder0->id(), item1->folder_id());
406 EXPECT_EQ("Item 0,Item 1", GetItemListContents(folder0->item_list()));
408 // Move item0 from folder0 to folder1.
409 model_.MoveItemToFolder(item0, folder1->id());
410 ASSERT_EQ(1u, folder0->item_list()->item_count());
411 ASSERT_EQ(1u, folder1->item_list()->item_count());
412 EXPECT_EQ(folder1->id(), item0->folder_id());
413 EXPECT_EQ("Item 1", GetItemListContents(folder0->item_list()));
414 EXPECT_EQ("Item 0", GetItemListContents(folder1->item_list()));
416 // Move item1 from folder0 to folder1. folder0 should get deleted.
417 model_.MoveItemToFolder(item1, folder1->id());
418 ASSERT_EQ(1u, model_.top_level_item_list()->item_count());
419 ASSERT_EQ(2u, folder1->item_list()->item_count());
420 EXPECT_EQ(folder1->id(), item1->folder_id());
421 EXPECT_EQ("Item 0,Item 1", GetItemListContents(folder1->item_list()));
423 // Move item1 to a non-existant folder2 which should get created.
424 model_.MoveItemToFolder(item1, "folder2");
425 ASSERT_EQ(2u, model_.top_level_item_list()->item_count());
426 ASSERT_EQ(1u, folder1->item_list()->item_count());
427 EXPECT_EQ("folder2", item1->folder_id());
428 AppListFolderItem* folder2 = model_.FindFolderItem("folder2");
429 ASSERT_TRUE(folder2);
432 TEST_F(AppListModelFolderTest, FindItemInFolder) {
433 AppListFolderItem* folder =
434 new AppListFolderItem("folder1", AppListFolderItem::FOLDER_TYPE_NORMAL);
435 EXPECT_TRUE(folder);
436 model_.AddItem(folder);
437 std::string folder_id = folder->id();
438 AppListItem* item0 = new AppListItem("Item 0");
439 model_.AddItemToFolder(item0, folder_id);
440 AppListItem* found_item = model_.FindItem(item0->id());
441 ASSERT_EQ(item0, found_item);
442 EXPECT_EQ(folder_id, found_item->folder_id());
445 TEST_F(AppListModelFolderTest, OemFolder) {
446 AppListFolderItem* folder =
447 new AppListFolderItem("folder1", AppListFolderItem::FOLDER_TYPE_OEM);
448 model_.AddItem(folder);
449 std::string folder_id = folder->id();
451 // Should not be able to move to an OEM folder with MergeItems.
452 AppListItem* item0 = new AppListItem("Item 0");
453 model_.AddItem(item0);
454 syncer::StringOrdinal item0_pos = item0->position();
455 std::string new_folder = model_.MergeItems(folder_id, item0->id());
456 EXPECT_EQ("", new_folder);
457 EXPECT_EQ("", item0->folder_id());
458 EXPECT_TRUE(item0->position().Equals(item0_pos));
460 // Should not be able to move from an OEM folder with MoveItemToFolderAt.
461 AppListItem* item1 = new AppListItem("Item 1");
462 model_.AddItemToFolder(item1, folder_id);
463 syncer::StringOrdinal item1_pos = item1->position();
464 bool move_res = model_.MoveItemToFolderAt(item1, "", syncer::StringOrdinal());
465 EXPECT_FALSE(move_res);
466 EXPECT_TRUE(item1->position().Equals(item1_pos));
469 } // namespace app_list