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/launcher/launcher.h"
9#include "ash/launcher/launcher_types.h"
10#include "ash/shelf/shelf_model.h"
11#include "base/command_line.h"
12#include "base/compiler_specific.h"
13#include "testing/gtest/include/gtest/gtest.h"
14
15namespace ash {
16
17namespace {
18
19class LauncherNavigatorTest : public testing::Test {
20 public:
21  LauncherNavigatorTest() {}
22
23 protected:
24  virtual void SetUp() OVERRIDE {
25    model_.reset(new ShelfModel);
26
27    // Add APP_LIST for test.
28    LauncherItem 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    LauncherItem browser_shortcut;
39    browser_shortcut.type = TYPE_BROWSER_SHORTCUT;
40    model_->Add(browser_shortcut);
41  }
42
43  void SetupMockShelfModel(LauncherItemType* types,
44                              int types_length,
45                              int focused_index) {
46    for (int i = 0; i < types_length; ++i) {
47      LauncherItem 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      LauncherItem 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(LauncherNavigatorTest);
70};
71
72class LauncherNavigatorLegacyShelfLayoutTest : public LauncherNavigatorTest {
73 public:
74  LauncherNavigatorLegacyShelfLayoutTest() : LauncherNavigatorTest() {}
75
76 protected:
77  virtual void SetUp() OVERRIDE {
78    CommandLine::ForCurrentProcess()->AppendSwitch(
79      ash::switches::kAshDisableAlternateShelfLayout);
80    LauncherNavigatorTest::SetUp();
81  }
82
83 private:
84  DISALLOW_COPY_AND_ASSIGN(LauncherNavigatorLegacyShelfLayoutTest);
85};
86
87}  // namespace
88
89TEST_F(LauncherNavigatorTest, BasicCycle) {
90  // An app shortcut and three platform apps.
91  LauncherItemType types[] = {
92    TYPE_APP_SHORTCUT, TYPE_PLATFORM_APP, TYPE_PLATFORM_APP, TYPE_PLATFORM_APP,
93  };
94  // ShelfModel automatically adds BROWSER_SHORTCUT item at the
95  // beginning, so '3' refers the first TYPE_PLATFORM_APP item.
96  SetupMockShelfModel(types, arraysize(types), 3);
97
98  EXPECT_EQ(4, GetNextActivatedItemIndex(model(), CYCLE_FORWARD));
99
100  // Fourth one.  It will skip the APP_SHORTCUT at the beginning of the list and
101  // the APP_LIST item which is automatically added at the end of items.
102  EXPECT_EQ(5, GetNextActivatedItemIndex(model(), CYCLE_BACKWARD));
103}
104
105TEST_F(LauncherNavigatorLegacyShelfLayoutTest, BasicCycle) {
106  // An app shortcut and three platform apps.
107  LauncherItemType types[] = {
108    TYPE_APP_SHORTCUT, TYPE_PLATFORM_APP, TYPE_PLATFORM_APP, TYPE_PLATFORM_APP,
109  };
110  // ShelfModel automatically adds BROWSER_SHORTCUT item at the
111  // beginning, so '2' refers the first TYPE_PLATFORM_APP item.
112  SetupMockShelfModel(types, arraysize(types), 2);
113
114  EXPECT_EQ(3, GetNextActivatedItemIndex(model(), CYCLE_FORWARD));
115
116  // Fourth one.  It will skip the APP_SHORTCUT at the beginning of the list and
117  // the APP_LIST item which is automatically added at the end of items.
118  EXPECT_EQ(4, GetNextActivatedItemIndex(model(), CYCLE_BACKWARD));
119}
120
121TEST_F(LauncherNavigatorTest, WrapToBeginning) {
122  LauncherItemType types[] = {
123    TYPE_APP_SHORTCUT, TYPE_PLATFORM_APP, TYPE_PLATFORM_APP, TYPE_PLATFORM_APP,
124  };
125  SetupMockShelfModel(types, arraysize(types), 5);
126
127  // Second one.  It skips the APP_LIST item at the end of the list,
128  // wraps to the beginning, and skips BROWSER_SHORTCUT and APP_SHORTCUT
129  // at the beginning of the list.
130  EXPECT_EQ(3, GetNextActivatedItemIndex(model(), CYCLE_FORWARD));
131}
132
133TEST_F(LauncherNavigatorLegacyShelfLayoutTest, WrapToBeginning) {
134  LauncherItemType types[] = {
135    TYPE_APP_SHORTCUT, TYPE_PLATFORM_APP, TYPE_PLATFORM_APP, TYPE_PLATFORM_APP,
136  };
137  SetupMockShelfModel(types, arraysize(types), 4);
138
139  // Second one.  It skips the APP_LIST item at the end of the list,
140  // wraps to the beginning, and skips BROWSER_SHORTCUT and APP_SHORTCUT
141  // at the beginning of the list.
142  EXPECT_EQ(2, GetNextActivatedItemIndex(model(), CYCLE_FORWARD));
143}
144
145TEST_F(LauncherNavigatorTest, Empty) {
146  SetupMockShelfModel(NULL, 0, -1);
147  EXPECT_EQ(-1, GetNextActivatedItemIndex(model(), CYCLE_FORWARD));
148  EXPECT_EQ(-1, GetNextActivatedItemIndex(model(), CYCLE_BACKWARD));
149}
150
151TEST_F(LauncherNavigatorTest, SingleEntry) {
152  LauncherItemType type = TYPE_PLATFORM_APP;
153  SetupMockShelfModel(&type, 1, 2);
154
155  // If there's only one item there and it is already active, there's no item
156  // to be activated next.
157  EXPECT_EQ(-1, GetNextActivatedItemIndex(model(), CYCLE_FORWARD));
158  EXPECT_EQ(-1, GetNextActivatedItemIndex(model(), CYCLE_BACKWARD));
159}
160
161TEST_F(LauncherNavigatorLegacyShelfLayoutTest, SingleEntry) {
162  LauncherItemType type = TYPE_PLATFORM_APP;
163  SetupMockShelfModel(&type, 1, 1);
164
165  // If there's only one item there and it is already active, there's no item
166  // to be activated next.
167  EXPECT_EQ(-1, GetNextActivatedItemIndex(model(), CYCLE_FORWARD));
168  EXPECT_EQ(-1, GetNextActivatedItemIndex(model(), CYCLE_BACKWARD));
169}
170
171TEST_F(LauncherNavigatorTest, NoActive) {
172  LauncherItemType types[] = {
173    TYPE_PLATFORM_APP, TYPE_PLATFORM_APP,
174  };
175  // Special case: no items are 'STATUS_ACTIVE'.
176  SetupMockShelfModel(types, arraysize(types), -1);
177
178  // If there are no active status, pick the first running item as a fallback.
179  EXPECT_EQ(2, GetNextActivatedItemIndex(model(), CYCLE_FORWARD));
180  EXPECT_EQ(2, GetNextActivatedItemIndex(model(), CYCLE_BACKWARD));
181}
182
183TEST_F(LauncherNavigatorLegacyShelfLayoutTest, NoActive) {
184  LauncherItemType types[] = {
185    TYPE_PLATFORM_APP, TYPE_PLATFORM_APP,
186  };
187  // Special case: no items are 'STATUS_ACTIVE'.
188  SetupMockShelfModel(types, arraysize(types), -1);
189
190  // If there are no active status, pick the first running item as a fallback.
191  EXPECT_EQ(1, GetNextActivatedItemIndex(model(), CYCLE_FORWARD));
192  EXPECT_EQ(1, GetNextActivatedItemIndex(model(), CYCLE_BACKWARD));
193}
194
195}  // namespace ash
196