Add Flex to views::BoxLayout.
[chromium-blink-merge.git] / ui / app_list / app_list_model_unittest.cc
blobb88a964fe2c64097eaa70850a73c0d97a9c7c805
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 model_.SetFoldersEnabled(true);
237 virtual ~AppListModelFolderTest() {}
239 // testing::Test overrides:
240 virtual void SetUp() OVERRIDE {
241 AppListModelTest::SetUp();
243 virtual void TearDown() OVERRIDE {
244 AppListModelTest::TearDown();
247 private:
248 DISALLOW_COPY_AND_ASSIGN(AppListModelFolderTest);
251 TEST_F(AppListModelFolderTest, FolderItem) {
252 AppListFolderItem* folder =
253 new AppListFolderItem("folder1", AppListFolderItem::FOLDER_TYPE_NORMAL);
254 const size_t num_folder_apps = 8;
255 const size_t num_observed_apps = 4;
256 model_.AddItem(folder);
257 for (int i = 0; static_cast<size_t>(i) < num_folder_apps; ++i) {
258 std::string name = model_.GetItemName(i);
259 model_.AddItemToFolder(model_.CreateItem(name), folder->id());
261 ASSERT_EQ(num_folder_apps, folder->item_list()->item_count());
262 // Check that items 0 and 3 are observed.
263 EXPECT_TRUE(ItemObservedByFolder(
264 folder, folder->item_list()->item_at(0)));
265 EXPECT_TRUE(ItemObservedByFolder(
266 folder, folder->item_list()->item_at(num_observed_apps - 1)));
267 // Check that item 4 is not observed.
268 EXPECT_FALSE(ItemObservedByFolder(
269 folder, folder->item_list()->item_at(num_observed_apps)));
270 folder->item_list()->MoveItem(num_observed_apps, 0);
271 // Confirm that everything was moved where expected.
272 EXPECT_EQ(model_.GetItemName(num_observed_apps),
273 folder->item_list()->item_at(0)->id());
274 EXPECT_EQ(model_.GetItemName(0),
275 folder->item_list()->item_at(1)->id());
276 EXPECT_EQ(model_.GetItemName(num_observed_apps - 1),
277 folder->item_list()->item_at(num_observed_apps)->id());
278 // Check that items 0 and 3 are observed.
279 EXPECT_TRUE(ItemObservedByFolder(
280 folder, folder->item_list()->item_at(0)));
281 EXPECT_TRUE(ItemObservedByFolder(
282 folder, folder->item_list()->item_at(num_observed_apps - 1)));
283 // Check that item 4 is not observed.
284 EXPECT_FALSE(ItemObservedByFolder(
285 folder, folder->item_list()->item_at(num_observed_apps)));
288 TEST_F(AppListModelFolderTest, MergeItems) {
289 model_.PopulateApps(3);
290 ASSERT_EQ(3u, model_.top_level_item_list()->item_count());
291 AppListItem* item0 = model_.top_level_item_list()->item_at(0);
292 AppListItem* item1 = model_.top_level_item_list()->item_at(1);
293 AppListItem* item2 = model_.top_level_item_list()->item_at(2);
295 // Merge two items.
296 std::string folder1_id = model_.MergeItems(item0->id(), item1->id());
297 ASSERT_EQ(2u, model_.top_level_item_list()->item_count()); // Folder + 1 item
298 AppListFolderItem* folder1_item = model_.FindFolderItem(folder1_id);
299 ASSERT_TRUE(folder1_item);
300 EXPECT_EQ("Item 0,Item 1", GetItemListContents(folder1_item->item_list()));
302 // Merge an item from the new folder into the third item.
303 std::string folder2_id = model_.MergeItems(item2->id(), item1->id());
304 ASSERT_EQ(2u, model_.top_level_item_list()->item_count()); // 2 folders
305 AppListFolderItem* folder2_item = model_.FindFolderItem(folder2_id);
306 EXPECT_EQ("Item 0", GetItemListContents(folder1_item->item_list()));
307 EXPECT_EQ("Item 2,Item 1", GetItemListContents(folder2_item->item_list()));
309 // Merge the remaining item to the new folder, ensure it is added to the end.
310 std::string folder_id = model_.MergeItems(folder2_id, item0->id());
311 EXPECT_EQ(folder2_id, folder_id);
312 EXPECT_EQ("Item 2,Item 1,Item 0",
313 GetItemListContents(folder2_item->item_list()));
315 // The empty folder should be deleted.
316 folder1_item = model_.FindFolderItem(folder1_id);
317 EXPECT_FALSE(folder1_item);
320 TEST_F(AppListModelFolderTest, AddItemToFolder) {
321 AppListFolderItem* folder =
322 new AppListFolderItem("folder1", AppListFolderItem::FOLDER_TYPE_NORMAL);
323 model_.AddItem(folder);
324 AppListItem* item0 = new AppListItem("Item 0");
325 model_.AddItemToFolder(item0, folder->id());
326 ASSERT_EQ(1u, model_.top_level_item_list()->item_count());
327 AppListFolderItem* folder_item = model_.FindFolderItem(folder->id());
328 ASSERT_TRUE(folder_item);
329 ASSERT_EQ(1u, folder_item->item_list()->item_count());
330 EXPECT_EQ(item0, folder_item->item_list()->item_at(0));
331 EXPECT_EQ(folder->id(), item0->folder_id());
334 TEST_F(AppListModelFolderTest, MoveItemToFolder) {
335 AppListFolderItem* folder =
336 new AppListFolderItem("folder1", AppListFolderItem::FOLDER_TYPE_NORMAL);
337 model_.AddItem(folder);
338 AppListItem* item0 = new AppListItem("Item 0");
339 AppListItem* item1 = new AppListItem("Item 1");
340 model_.AddItem(item0);
341 model_.AddItem(item1);
342 ASSERT_EQ(3u, model_.top_level_item_list()->item_count());
343 // Move item0 and item1 to folder.
344 std::string folder_id = folder->id();
345 model_.MoveItemToFolder(item0, folder_id);
346 model_.MoveItemToFolder(item1, folder_id);
347 AppListFolderItem* folder_item = model_.FindFolderItem(folder_id);
348 ASSERT_TRUE(folder_item);
349 EXPECT_EQ(folder_id, item0->folder_id());
350 EXPECT_EQ(folder_id, item1->folder_id());
351 EXPECT_EQ("Item 0,Item 1", GetItemListContents(folder_item->item_list()));
352 // Move item0 out of folder.
353 model_.MoveItemToFolder(item0, "");
354 EXPECT_EQ("", item0->folder_id());
355 folder_item = model_.FindFolderItem(folder_id);
356 ASSERT_TRUE(folder_item);
357 // Move item1 out of folder, folder should be deleted.
358 model_.MoveItemToFolder(item1, "");
359 EXPECT_EQ("", item1->folder_id());
360 folder_item = model_.FindFolderItem(folder_id);
361 EXPECT_FALSE(folder_item);
364 TEST_F(AppListModelFolderTest, MoveItemToFolderAt) {
365 model_.AddItem(new AppListItem("Item 0"));
366 model_.AddItem(new AppListItem("Item 1"));
367 AppListFolderItem* folder1 = static_cast<AppListFolderItem*>(model_.AddItem(
368 new AppListFolderItem("folder1", AppListFolderItem::FOLDER_TYPE_NORMAL)));
369 model_.AddItem(new AppListItem("Item 2"));
370 model_.AddItem(new AppListItem("Item 3"));
371 ASSERT_EQ(5u, model_.top_level_item_list()->item_count());
372 EXPECT_EQ("Item 0,Item 1,folder1,Item 2,Item 3", GetModelContents());
373 // Move Item 1 to folder1, then Item 2 before Item 1.
374 model_.MoveItemToFolderAt(model_.top_level_item_list()->item_at(1),
375 folder1->id(),
376 syncer::StringOrdinal());
377 EXPECT_EQ("Item 0,folder1,Item 2,Item 3", GetModelContents());
378 model_.MoveItemToFolderAt(model_.top_level_item_list()->item_at(2),
379 folder1->id(),
380 folder1->item_list()->item_at(0)->position());
381 EXPECT_EQ("Item 2,Item 1", GetItemListContents(folder1->item_list()));
382 EXPECT_EQ("Item 0,folder1,Item 3", GetModelContents());
383 // Move Item 2 out of folder to before folder.
384 model_.MoveItemToFolderAt(
385 folder1->item_list()->item_at(0), "", folder1->position());
386 EXPECT_EQ("Item 0,Item 2,folder1,Item 3", GetModelContents());
387 // Move remaining folder item, (Item 1) out of folder to folder position.
388 ASSERT_EQ(1u, folder1->item_list()->item_count());
389 model_.MoveItemToFolderAt(
390 folder1->item_list()->item_at(0), "", folder1->position());
391 EXPECT_EQ("Item 0,Item 2,Item 1,Item 3", GetModelContents());
394 TEST_F(AppListModelFolderTest, MoveItemFromFolderToFolder) {
395 AppListFolderItem* folder0 =
396 new AppListFolderItem("folder0", AppListFolderItem::FOLDER_TYPE_NORMAL);
397 AppListFolderItem* folder1 =
398 new AppListFolderItem("folder1", AppListFolderItem::FOLDER_TYPE_NORMAL);
399 model_.AddItem(folder0);
400 model_.AddItem(folder1);
401 EXPECT_EQ("folder0,folder1", GetModelContents());
402 AppListItem* item0 = new AppListItem("Item 0");
403 AppListItem* item1 = new AppListItem("Item 1");
404 model_.AddItemToFolder(item0, folder0->id());
405 model_.AddItemToFolder(item1, folder0->id());
406 EXPECT_EQ(folder0->id(), item0->folder_id());
407 EXPECT_EQ(folder0->id(), item1->folder_id());
408 EXPECT_EQ("Item 0,Item 1", GetItemListContents(folder0->item_list()));
410 // Move item0 from folder0 to folder1.
411 model_.MoveItemToFolder(item0, folder1->id());
412 ASSERT_EQ(1u, folder0->item_list()->item_count());
413 ASSERT_EQ(1u, folder1->item_list()->item_count());
414 EXPECT_EQ(folder1->id(), item0->folder_id());
415 EXPECT_EQ("Item 1", GetItemListContents(folder0->item_list()));
416 EXPECT_EQ("Item 0", GetItemListContents(folder1->item_list()));
418 // Move item1 from folder0 to folder1. folder0 should get deleted.
419 model_.MoveItemToFolder(item1, folder1->id());
420 ASSERT_EQ(1u, model_.top_level_item_list()->item_count());
421 ASSERT_EQ(2u, folder1->item_list()->item_count());
422 EXPECT_EQ(folder1->id(), item1->folder_id());
423 EXPECT_EQ("Item 0,Item 1", GetItemListContents(folder1->item_list()));
425 // Move item1 to a non-existant folder2 which should get created.
426 model_.MoveItemToFolder(item1, "folder2");
427 ASSERT_EQ(2u, model_.top_level_item_list()->item_count());
428 ASSERT_EQ(1u, folder1->item_list()->item_count());
429 EXPECT_EQ("folder2", item1->folder_id());
430 AppListFolderItem* folder2 = model_.FindFolderItem("folder2");
431 ASSERT_TRUE(folder2);
434 TEST_F(AppListModelFolderTest, FindItemInFolder) {
435 AppListFolderItem* folder =
436 new AppListFolderItem("folder1", AppListFolderItem::FOLDER_TYPE_NORMAL);
437 EXPECT_TRUE(folder);
438 model_.AddItem(folder);
439 std::string folder_id = folder->id();
440 AppListItem* item0 = new AppListItem("Item 0");
441 model_.AddItemToFolder(item0, folder_id);
442 AppListItem* found_item = model_.FindItem(item0->id());
443 ASSERT_EQ(item0, found_item);
444 EXPECT_EQ(folder_id, found_item->folder_id());
447 TEST_F(AppListModelFolderTest, OemFolder) {
448 AppListFolderItem* folder =
449 new AppListFolderItem("folder1", AppListFolderItem::FOLDER_TYPE_OEM);
450 model_.AddItem(folder);
451 std::string folder_id = folder->id();
453 // Should not be able to move to an OEM folder with MergeItems.
454 AppListItem* item0 = new AppListItem("Item 0");
455 model_.AddItem(item0);
456 syncer::StringOrdinal item0_pos = item0->position();
457 std::string new_folder = model_.MergeItems(folder_id, item0->id());
458 EXPECT_EQ("", new_folder);
459 EXPECT_EQ("", item0->folder_id());
460 EXPECT_TRUE(item0->position().Equals(item0_pos));
462 // Should not be able to move from an OEM folder with MoveItemToFolderAt.
463 AppListItem* item1 = new AppListItem("Item 1");
464 model_.AddItemToFolder(item1, folder_id);
465 syncer::StringOrdinal item1_pos = item1->position();
466 bool move_res = model_.MoveItemToFolderAt(item1, "", syncer::StringOrdinal());
467 EXPECT_FALSE(move_res);
468 EXPECT_TRUE(item1->position().Equals(item1_pos));
471 TEST_F(AppListModelFolderTest, DisableFolders) {
472 // Set up a folder with two items and an OEM folder with one item.
473 AppListFolderItem* folder =
474 new AppListFolderItem("folder1", AppListFolderItem::FOLDER_TYPE_NORMAL);
475 model_.AddItem(folder);
476 std::string folder_id = folder->id();
477 AppListItem* item0 = new AppListItem("Item 0");
478 model_.AddItemToFolder(item0, folder_id);
479 AppListItem* item1 = new AppListItem("Item 1");
480 model_.AddItemToFolder(item1, folder_id);
481 AppListFolderItem* folder_item = model_.FindFolderItem(folder_id);
482 ASSERT_TRUE(folder_item);
483 EXPECT_EQ(2u, folder_item->item_list()->item_count());
484 AppListFolderItem* oem_folder =
485 new AppListFolderItem("oem_folder", AppListFolderItem::FOLDER_TYPE_OEM);
486 model_.AddItem(oem_folder);
487 AppListItem* oem_item = new AppListItem("OEM Item");
488 std::string oem_folder_id = oem_folder->id();
489 model_.AddItemToFolder(oem_item, oem_folder_id);
490 EXPECT_EQ("folder1,oem_folder", GetModelContents());
492 // Disable folders. Ensure non-oem folder is removed.
493 model_.SetFoldersEnabled(false);
494 ASSERT_FALSE(model_.FindFolderItem(folder_id));
495 ASSERT_TRUE(model_.FindFolderItem(oem_folder_id));
496 EXPECT_EQ("Item 0,Item 1,oem_folder", GetModelContents());
498 // Ensure folder creation fails.
499 EXPECT_EQ(std::string(), model_.MergeItems(item0->id(), item1->id()));
502 } // namespace app_list