1f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "ash/shelf/shelf_model.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <set>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string>
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "ash/ash_switches.h"
11f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "ash/shelf/shelf_model_observer.h"
1258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "base/command_line.h"
13868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/stringprintf.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace ash {
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// ShelfModelObserver implementation that tracks what message are invoked.
21f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)class TestShelfModelObserver : public ShelfModelObserver {
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
23f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  TestShelfModelObserver()
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : added_count_(0),
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        removed_count_(0),
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        changed_count_(0),
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        moved_count_(0) {
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Returns a string description of the changes that have occurred since this
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // was last invoked. Resets state to initial state.
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string StateStringAndClear() {
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string result;
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AddToResult("added=%d", added_count_, &result);
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AddToResult("removed=%d", removed_count_, &result);
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AddToResult("changed=%d", changed_count_, &result);
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AddToResult("moved=%d", moved_count_, &result);
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    added_count_ = removed_count_ = changed_count_ = moved_count_ = 0;
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return result;
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
42f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // ShelfModelObserver overrides:
43f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  virtual void ShelfItemAdded(int index) OVERRIDE {
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    added_count_++;
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual void ShelfItemRemoved(int index, ShelfID id) OVERRIDE {
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    removed_count_++;
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
49f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  virtual void ShelfItemChanged(int index,
505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                const ShelfItem& old_item) OVERRIDE {
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    changed_count_++;
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
53f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  virtual void ShelfItemMoved(int start_index, int target_index) OVERRIDE {
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    moved_count_++;
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
56f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  virtual void ShelfStatusChanged() OVERRIDE {
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void AddToResult(const std::string& format, int count, std::string* result) {
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!count)
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!result->empty())
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *result += " ";
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *result += base::StringPrintf(format.c_str(), count);
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int added_count_;
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int removed_count_;
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int changed_count_;
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int moved_count_;
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
73f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(TestShelfModelObserver);
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
78f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)class ShelfModelTest : public testing::Test {
7958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) public:
80f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  ShelfModelTest() {}
81f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  virtual ~ShelfModelTest() {}
8258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
8358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  virtual void SetUp() {
84f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    model_.reset(new ShelfModel);
85f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    observer_.reset(new TestShelfModelObserver);
8658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    EXPECT_EQ(0, model_->item_count());
8758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    ShelfItem item;
8958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    item.type = TYPE_APP_LIST;
9058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    model_->Add(item);
9158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    EXPECT_EQ(1, model_->item_count());
9258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
9358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    model_->AddObserver(observer_.get());
9458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  virtual void TearDown() {
9758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    observer_.reset();
9858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    model_.reset();
9958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
10058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
101f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  scoped_ptr<ShelfModel> model_;
102f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  scoped_ptr<TestShelfModelObserver> observer_;
10358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
10458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) private:
105f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(ShelfModelTest);
10658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)};
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
108f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)TEST_F(ShelfModelTest, BasicAssertions) {
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Add an item.
1105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ShelfItem item;
111424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  item.type = TYPE_APP_SHORTCUT;
11258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  int index = model_->Add(item);
11358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  EXPECT_EQ(2, model_->item_count());
11458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  EXPECT_EQ("added=1", observer_->StateStringAndClear());
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
116424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // Change to a platform app item.
1175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ShelfID original_id = model_->items()[index].id;
118424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  item.type = TYPE_PLATFORM_APP;
11958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  model_->Set(index, item);
12058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  EXPECT_EQ(original_id, model_->items()[index].id);
12158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  EXPECT_EQ("changed=1", observer_->StateStringAndClear());
12258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  EXPECT_EQ(TYPE_PLATFORM_APP, model_->items()[index].type);
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Remove the item.
12558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  model_->RemoveItemAt(index);
12658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  EXPECT_EQ(1, model_->item_count());
12758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  EXPECT_EQ("removed=1", observer_->StateStringAndClear());
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Add an app item.
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  item.type = TYPE_APP_SHORTCUT;
13158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  index = model_->Add(item);
13258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  observer_->StateStringAndClear();
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Change everything.
13558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  model_->Set(index, item);
13658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  EXPECT_EQ("changed=1", observer_->StateStringAndClear());
13758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  EXPECT_EQ(TYPE_APP_SHORTCUT, model_->items()[index].type);
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Add another item.
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  item.type = TYPE_APP_SHORTCUT;
14158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  model_->Add(item);
14258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  observer_->StateStringAndClear();
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // Move the second to the first.
14558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  model_->Move(1, 0);
14658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  EXPECT_EQ("moved=1", observer_->StateStringAndClear());
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // And back.
14958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  model_->Move(0, 1);
15058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  EXPECT_EQ("moved=1", observer_->StateStringAndClear());
15158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
15258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // Verifies all the items get unique ids.
1535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::set<ShelfID> ids;
15458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  for (int i = 0; i < model_->item_count(); ++i)
15558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    ids.insert(model_->items()[i].id);
15658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  EXPECT_EQ(model_->item_count(), static_cast<int>(ids.size()));
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Assertions around where items are added.
160f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)TEST_F(ShelfModelTest, AddIndices) {
16158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // Insert browser short cut at index 1.
1625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ShelfItem browser_shortcut;
16358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  browser_shortcut.type = TYPE_BROWSER_SHORTCUT;
16458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  int browser_shortcut_index = model_->Add(browser_shortcut);
16558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  EXPECT_EQ(1, browser_shortcut_index);
16658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
16758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // platform app items should be after browser shortcut.
1685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ShelfItem item;
16958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  item.type = TYPE_PLATFORM_APP;
17058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  int platform_app_index1 = model_->Add(item);
17158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  EXPECT_EQ(2, platform_app_index1);
17258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
17358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // Add another platform app item, it should follow first.
17458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  int platform_app_index2 = model_->Add(item);
17558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  EXPECT_EQ(3, platform_app_index2);
17658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
17758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // APP_SHORTCUT priority is higher than PLATFORM_APP but same as
17858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // BROWSER_SHORTCUT. So APP_SHORTCUT is located after BROWSER_SHORCUT.
17958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  item.type = TYPE_APP_SHORTCUT;
18058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  int app_shortcut_index1 = model_->Add(item);
18158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  EXPECT_EQ(2, app_shortcut_index1);
18258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
18358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  item.type = TYPE_APP_SHORTCUT;
18458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  int app_shortcut_index2 = model_->Add(item);
18558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  EXPECT_EQ(3, app_shortcut_index2);
18658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
18758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // Check that AddAt() figures out the correct indexes for app shortcuts.
18858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // APP_SHORTCUT and BROWSER_SHORTCUT has the same weight.
18958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // So APP_SHORTCUT is located at index 0. And, BROWSER_SHORTCUT is located at
19058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // index 1.
19158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  item.type = TYPE_APP_SHORTCUT;
19258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  int app_shortcut_index3 = model_->AddAt(1, item);
19358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  EXPECT_EQ(1, app_shortcut_index3);
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  item.type = TYPE_APP_SHORTCUT;
19658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  int app_shortcut_index4 = model_->AddAt(6, item);
19758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  EXPECT_EQ(5, app_shortcut_index4);
19858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
19958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  item.type = TYPE_APP_SHORTCUT;
20058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  int app_shortcut_index5 = model_->AddAt(3, item);
20158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  EXPECT_EQ(3, app_shortcut_index5);
20258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
20358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // Before there are any panels, no icons should be right aligned.
20458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  EXPECT_EQ(model_->item_count(), model_->FirstPanelIndex());
20558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
20658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // Check that AddAt() figures out the correct indexes for platform apps and
20758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // panels.
20858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  item.type = TYPE_PLATFORM_APP;
20958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  int platform_app_index3 = model_->AddAt(3, item);
21058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  EXPECT_EQ(7, platform_app_index3);
21158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
21258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  item.type = TYPE_APP_PANEL;
21358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  int app_panel_index1 = model_->AddAt(2, item);
21458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  EXPECT_EQ(10, app_panel_index1);
21558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
21658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  item.type = TYPE_PLATFORM_APP;
21758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  int platform_app_index4 = model_->AddAt(11, item);
21858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  EXPECT_EQ(10, platform_app_index4);
21958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
22058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  item.type = TYPE_APP_PANEL;
22158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  int app_panel_index2 = model_->AddAt(12, item);
22258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  EXPECT_EQ(12, app_panel_index2);
22358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
22458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  item.type = TYPE_PLATFORM_APP;
22558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  int platform_app_index5 = model_->AddAt(7, item);
22658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  EXPECT_EQ(7, platform_app_index5);
22758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
22858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  item.type = TYPE_APP_PANEL;
22958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  int app_panel_index3 = model_->AddAt(13, item);
23058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  EXPECT_EQ(13, app_panel_index3);
23158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
23258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // Right aligned index should be the first app panel index.
23358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  EXPECT_EQ(12, model_->FirstPanelIndex());
23458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
23558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  EXPECT_EQ(TYPE_BROWSER_SHORTCUT, model_->items()[2].type);
23658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  EXPECT_EQ(TYPE_APP_LIST, model_->items()[0].type);
23758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
23858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
2395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Test that the indexes for the running applications are properly determined
2405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// when the first running application is a windowed application.
2415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(ShelfModelTest, FirstRunningAppIndexUsingWindowedAppFirst) {
2425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Insert the browser shortcut at index 1 and check that the running
2435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // application index would be behind it.
2445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ShelfItem item;
2455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  item.type = TYPE_BROWSER_SHORTCUT;
2465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(1, model_->Add(item));
2475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(2, model_->FirstRunningAppIndex());
2485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Insert a panel application at the end and check that the running
2505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // application index would be at / before the application panel.
2515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  item.type = TYPE_APP_PANEL;
2525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(2, model_->Add(item));
2535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(2, model_->FirstRunningAppIndex());
2545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Insert an application shortcut and make sure that the running application
2565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // index would be behind it.
2575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  item.type = TYPE_APP_SHORTCUT;
2585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(2, model_->Add(item));
2595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(3, model_->FirstRunningAppIndex());
2605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Insert different running application shortcuts - but first a windowed
2625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // application - and make sure that the same index gets returned.
2635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  item.type = TYPE_WINDOWED_APP;
2645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  int running_app_index = model_->Add(item);
2655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(3, running_app_index);
2665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(running_app_index, model_->FirstRunningAppIndex());
2675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  item.type = TYPE_PLATFORM_APP;
2685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(running_app_index + 1, model_->Add(item));
2695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(running_app_index, model_->FirstRunningAppIndex());
2705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Test that the indexes for the running applications are properly determined
2735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// when the first running application is a platform application.
2745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(ShelfModelTest, FirstRunningAppIndexUsingPlatformAppFirst) {
2755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Insert the browser shortcut at index 1 and check that the running
2765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // application index would be behind it.
2775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ShelfItem item;
2785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  item.type = TYPE_BROWSER_SHORTCUT;
2795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(1, model_->Add(item));
2805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(2, model_->FirstRunningAppIndex());
2815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Insert a panel application at the end and check that the running
2835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // application index would be at / before the application panel.
2845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  item.type = TYPE_APP_PANEL;
2855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(2, model_->Add(item));
2865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(2, model_->FirstRunningAppIndex());
2875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Insert an application shortcut and make sure that the running application
2895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // index would be behind it.
2905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  item.type = TYPE_APP_SHORTCUT;
2915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(2, model_->Add(item));
2925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(3, model_->FirstRunningAppIndex());
2935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Insert different running application shortcuts - but first a platfom
2955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // application - and make sure that the same index gets returned.
2965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  item.type = TYPE_PLATFORM_APP;
2975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  int running_app_index = model_->Add(item);
2985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(3, running_app_index);
2995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(running_app_index, model_->FirstRunningAppIndex());
3005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  item.type = TYPE_WINDOWED_APP;
3015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(running_app_index + 1, model_->Add(item));
3025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(running_app_index, model_->FirstRunningAppIndex());
3035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
3045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Assertions around id generation and usage.
3065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(ShelfModelTest, ShelfIDTests) {
3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Get the next to use ID counter.
3085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ShelfID id = model_->next_id();
3092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Calling this function multiple times does not change the returned ID.
31158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  EXPECT_EQ(model_->next_id(), id);
3122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Check that when we reserve a value it will be the previously retrieved ID,
3142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // but it will not change the item count and retrieving the next ID should
3152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // produce something new.
31658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  EXPECT_EQ(model_->reserve_external_id(), id);
31758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  EXPECT_EQ(1, model_->item_count());
3185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ShelfID id2 = model_->next_id();
3192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_NE(id2, id);
3202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Adding another item to the list should also produce a new ID.
3225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ShelfItem item;
323424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  item.type = TYPE_PLATFORM_APP;
32458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  model_->Add(item);
32558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  EXPECT_NE(model_->next_id(), id2);
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3287d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// This verifies that converting an existing item into a lower weight category
3297d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// (e.g. shortcut to running but not pinned app) will move it to the proper
3307d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// location. See crbug.com/248769.
331f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)TEST_F(ShelfModelTest, CorrectMoveItemsWhenStateChange) {
33258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // The first item is the app list and last item is the browser.
3335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ShelfItem browser_shortcut;
33458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  browser_shortcut.type = TYPE_BROWSER_SHORTCUT;
33558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  int browser_shortcut_index = model_->Add(browser_shortcut);
33658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  EXPECT_EQ(TYPE_APP_LIST, model_->items()[0].type);
33758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  EXPECT_EQ(1, browser_shortcut_index);
33858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
33958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // Add three shortcuts. They should all be moved between the two.
3405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ShelfItem item;
34158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  item.type = TYPE_APP_SHORTCUT;
34258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  int app1_index = model_->Add(item);
34358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  EXPECT_EQ(2, app1_index);
34458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  int app2_index = model_->Add(item);
34558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  EXPECT_EQ(3, app2_index);
34658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  int app3_index = model_->Add(item);
34758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  EXPECT_EQ(4, app3_index);
34858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
34958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // Now change the type of the second item and make sure that it is moving
35058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // behind the shortcuts.
35158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  item.type = TYPE_PLATFORM_APP;
35258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  model_->Set(app2_index, item);
35358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
35458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // The item should have moved in front of the app launcher.
35558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  EXPECT_EQ(TYPE_PLATFORM_APP, model_->items()[4].type);
35658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
3577d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace ash
359