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.
4
5#include "ash/shelf/shelf_navigator.h"
6
7#include "ash/ash_switches.h"
8#include "ash/shelf/shelf.h"
9#include "ash/shelf/shelf_item_types.h"
10#include "ash/shelf/shelf_model.h"
11#include "base/command_line.h"
12#include "base/macros.h"
13#include "testing/gtest/include/gtest/gtest.h"
14
15namespace ash {
16
17namespace {
18
19class ShelfNavigatorTest : public testing::Test {
20 public:
21  ShelfNavigatorTest() {}
22
23 protected:
24  virtual void SetUp() OVERRIDE {
25    model_.reset(new ShelfModel);
26
27    // Add APP_LIST for test.
28    ShelfItem app_list;
29    app_list.type = TYPE_APP_LIST;
30    model_->Add(app_list);
31
32    // Initially, applist launcher item is only created.
33    int total_num = model_->item_count();
34    EXPECT_EQ(1, total_num);
35    EXPECT_TRUE(model_->items()[0].type == TYPE_APP_LIST);
36
37    // Add BROWSER_SHORTCUT for test.
38    ShelfItem browser_shortcut;
39    browser_shortcut.type = TYPE_BROWSER_SHORTCUT;
40    model_->Add(browser_shortcut);
41  }
42
43  void SetupMockShelfModel(ShelfItemType* types,
44                           int types_length,
45                           int focused_index) {
46    for (int i = 0; i < types_length; ++i) {
47      ShelfItem new_item;
48      new_item.type = types[i];
49      new_item.status =
50          (types[i] == TYPE_PLATFORM_APP) ? STATUS_RUNNING : STATUS_CLOSED;
51      model_->Add(new_item);
52    }
53
54    // Set the focused item.
55    if (focused_index >= 0) {
56      ShelfItem focused_item =model_->items()[focused_index];
57      if (focused_item.type == TYPE_PLATFORM_APP) {
58        focused_item.status = STATUS_ACTIVE;
59        model_->Set(focused_index, focused_item);
60      }
61    }
62  }
63
64  const ShelfModel& model() { return *model_.get(); }
65
66 private:
67  scoped_ptr<ShelfModel> model_;
68
69  DISALLOW_COPY_AND_ASSIGN(ShelfNavigatorTest);
70};
71
72}  // namespace
73
74TEST_F(ShelfNavigatorTest, BasicCycle) {
75  // An app shortcut and three platform apps.
76  ShelfItemType types[] = {
77    TYPE_APP_SHORTCUT, TYPE_PLATFORM_APP, TYPE_PLATFORM_APP, TYPE_PLATFORM_APP,
78  };
79  // ShelfModel automatically adds BROWSER_SHORTCUT item at the
80  // beginning, so '3' refers the first TYPE_PLATFORM_APP item.
81  SetupMockShelfModel(types, arraysize(types), 3);
82
83  EXPECT_EQ(4, GetNextActivatedItemIndex(model(), CYCLE_FORWARD));
84
85  // Fourth one.  It will skip the APP_SHORTCUT at the beginning of the list and
86  // the APP_LIST item which is automatically added at the end of items.
87  EXPECT_EQ(5, GetNextActivatedItemIndex(model(), CYCLE_BACKWARD));
88}
89
90TEST_F(ShelfNavigatorTest, WrapToBeginning) {
91  ShelfItemType types[] = {
92    TYPE_APP_SHORTCUT, TYPE_PLATFORM_APP, TYPE_PLATFORM_APP, TYPE_PLATFORM_APP,
93  };
94  SetupMockShelfModel(types, arraysize(types), 5);
95
96  // Second one.  It skips the APP_LIST item at the end of the list,
97  // wraps to the beginning, and skips BROWSER_SHORTCUT and APP_SHORTCUT
98  // at the beginning of the list.
99  EXPECT_EQ(3, GetNextActivatedItemIndex(model(), CYCLE_FORWARD));
100}
101
102TEST_F(ShelfNavigatorTest, Empty) {
103  SetupMockShelfModel(NULL, 0, -1);
104  EXPECT_EQ(-1, GetNextActivatedItemIndex(model(), CYCLE_FORWARD));
105  EXPECT_EQ(-1, GetNextActivatedItemIndex(model(), CYCLE_BACKWARD));
106}
107
108TEST_F(ShelfNavigatorTest, SingleEntry) {
109  ShelfItemType type = TYPE_PLATFORM_APP;
110  SetupMockShelfModel(&type, 1, 2);
111
112  // If there's only one item there and it is already active, there's no item
113  // to be activated next.
114  EXPECT_EQ(-1, GetNextActivatedItemIndex(model(), CYCLE_FORWARD));
115  EXPECT_EQ(-1, GetNextActivatedItemIndex(model(), CYCLE_BACKWARD));
116}
117
118TEST_F(ShelfNavigatorTest, NoActive) {
119  ShelfItemType types[] = {
120    TYPE_PLATFORM_APP, TYPE_PLATFORM_APP,
121  };
122  // Special case: no items are 'STATUS_ACTIVE'.
123  SetupMockShelfModel(types, arraysize(types), -1);
124
125  // If there are no active status, pick the first running item as a fallback.
126  EXPECT_EQ(2, GetNextActivatedItemIndex(model(), CYCLE_FORWARD));
127  EXPECT_EQ(2, GetNextActivatedItemIndex(model(), CYCLE_BACKWARD));
128}
129
130}  // namespace ash
131