| OLD | NEW | 
 | (Empty) | 
|    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/common/shelf/shelf_model.h" |  | 
|    6  |  | 
|    7 #include <set> |  | 
|    8 #include <string> |  | 
|    9  |  | 
|   10 #include "ash/common/shelf/shelf_model_observer.h" |  | 
|   11 #include "base/strings/stringprintf.h" |  | 
|   12 #include "testing/gtest/include/gtest/gtest.h" |  | 
|   13  |  | 
|   14 namespace ash { |  | 
|   15  |  | 
|   16 namespace { |  | 
|   17  |  | 
|   18 // ShelfModelObserver implementation that tracks what message are invoked. |  | 
|   19 class TestShelfModelObserver : public ShelfModelObserver { |  | 
|   20  public: |  | 
|   21   TestShelfModelObserver() |  | 
|   22       : added_count_(0), |  | 
|   23         removed_count_(0), |  | 
|   24         changed_count_(0), |  | 
|   25         moved_count_(0) {} |  | 
|   26  |  | 
|   27   // Returns a string description of the changes that have occurred since this |  | 
|   28   // was last invoked. Resets state to initial state. |  | 
|   29   std::string StateStringAndClear() { |  | 
|   30     std::string result; |  | 
|   31     AddToResult("added=%d", added_count_, &result); |  | 
|   32     AddToResult("removed=%d", removed_count_, &result); |  | 
|   33     AddToResult("changed=%d", changed_count_, &result); |  | 
|   34     AddToResult("moved=%d", moved_count_, &result); |  | 
|   35     added_count_ = removed_count_ = changed_count_ = moved_count_ = 0; |  | 
|   36     return result; |  | 
|   37   } |  | 
|   38  |  | 
|   39   // ShelfModelObserver overrides: |  | 
|   40   void ShelfItemAdded(int index) override { added_count_++; } |  | 
|   41   void ShelfItemRemoved(int index, ShelfID id) override { removed_count_++; } |  | 
|   42   void ShelfItemChanged(int index, const ShelfItem& old_item) override { |  | 
|   43     changed_count_++; |  | 
|   44   } |  | 
|   45   void ShelfItemMoved(int start_index, int target_index) override { |  | 
|   46     moved_count_++; |  | 
|   47   } |  | 
|   48   void OnSetShelfItemDelegate(ShelfID id, |  | 
|   49                               ShelfItemDelegate* item_delegate) override {} |  | 
|   50  |  | 
|   51  private: |  | 
|   52   void AddToResult(const std::string& format, int count, std::string* result) { |  | 
|   53     if (!count) |  | 
|   54       return; |  | 
|   55     if (!result->empty()) |  | 
|   56       *result += " "; |  | 
|   57     *result += base::StringPrintf(format.c_str(), count); |  | 
|   58   } |  | 
|   59  |  | 
|   60   int added_count_; |  | 
|   61   int removed_count_; |  | 
|   62   int changed_count_; |  | 
|   63   int moved_count_; |  | 
|   64  |  | 
|   65   DISALLOW_COPY_AND_ASSIGN(TestShelfModelObserver); |  | 
|   66 }; |  | 
|   67  |  | 
|   68 }  // namespace |  | 
|   69  |  | 
|   70 class ShelfModelTest : public testing::Test { |  | 
|   71  public: |  | 
|   72   ShelfModelTest() {} |  | 
|   73   ~ShelfModelTest() override {} |  | 
|   74  |  | 
|   75   void SetUp() override { |  | 
|   76     model_.reset(new ShelfModel); |  | 
|   77     observer_.reset(new TestShelfModelObserver); |  | 
|   78     EXPECT_EQ(0, model_->item_count()); |  | 
|   79  |  | 
|   80     ShelfItem item; |  | 
|   81     item.type = TYPE_APP_LIST; |  | 
|   82     model_->Add(item); |  | 
|   83     EXPECT_EQ(1, model_->item_count()); |  | 
|   84  |  | 
|   85     model_->AddObserver(observer_.get()); |  | 
|   86   } |  | 
|   87  |  | 
|   88   void TearDown() override { |  | 
|   89     observer_.reset(); |  | 
|   90     model_.reset(); |  | 
|   91   } |  | 
|   92  |  | 
|   93   std::unique_ptr<ShelfModel> model_; |  | 
|   94   std::unique_ptr<TestShelfModelObserver> observer_; |  | 
|   95  |  | 
|   96  private: |  | 
|   97   DISALLOW_COPY_AND_ASSIGN(ShelfModelTest); |  | 
|   98 }; |  | 
|   99  |  | 
|  100 TEST_F(ShelfModelTest, BasicAssertions) { |  | 
|  101   // Add an item. |  | 
|  102   ShelfItem item; |  | 
|  103   item.type = TYPE_APP_SHORTCUT; |  | 
|  104   int index = model_->Add(item); |  | 
|  105   EXPECT_EQ(2, model_->item_count()); |  | 
|  106   EXPECT_EQ("added=1", observer_->StateStringAndClear()); |  | 
|  107  |  | 
|  108   // Change to a platform app item. |  | 
|  109   ShelfID original_id = model_->items()[index].id; |  | 
|  110   item.type = TYPE_APP; |  | 
|  111   model_->Set(index, item); |  | 
|  112   EXPECT_EQ(original_id, model_->items()[index].id); |  | 
|  113   EXPECT_EQ("changed=1", observer_->StateStringAndClear()); |  | 
|  114   EXPECT_EQ(TYPE_APP, model_->items()[index].type); |  | 
|  115  |  | 
|  116   // Remove the item. |  | 
|  117   model_->RemoveItemAt(index); |  | 
|  118   EXPECT_EQ(1, model_->item_count()); |  | 
|  119   EXPECT_EQ("removed=1", observer_->StateStringAndClear()); |  | 
|  120  |  | 
|  121   // Add an app item. |  | 
|  122   item.type = TYPE_APP_SHORTCUT; |  | 
|  123   index = model_->Add(item); |  | 
|  124   observer_->StateStringAndClear(); |  | 
|  125  |  | 
|  126   // Change everything. |  | 
|  127   model_->Set(index, item); |  | 
|  128   EXPECT_EQ("changed=1", observer_->StateStringAndClear()); |  | 
|  129   EXPECT_EQ(TYPE_APP_SHORTCUT, model_->items()[index].type); |  | 
|  130  |  | 
|  131   // Add another item. |  | 
|  132   item.type = TYPE_APP_SHORTCUT; |  | 
|  133   model_->Add(item); |  | 
|  134   observer_->StateStringAndClear(); |  | 
|  135  |  | 
|  136   // Move the second to the first. |  | 
|  137   model_->Move(1, 0); |  | 
|  138   EXPECT_EQ("moved=1", observer_->StateStringAndClear()); |  | 
|  139  |  | 
|  140   // And back. |  | 
|  141   model_->Move(0, 1); |  | 
|  142   EXPECT_EQ("moved=1", observer_->StateStringAndClear()); |  | 
|  143  |  | 
|  144   // Verifies all the items get unique ids. |  | 
|  145   std::set<ShelfID> ids; |  | 
|  146   for (int i = 0; i < model_->item_count(); ++i) |  | 
|  147     ids.insert(model_->items()[i].id); |  | 
|  148   EXPECT_EQ(model_->item_count(), static_cast<int>(ids.size())); |  | 
|  149 } |  | 
|  150  |  | 
|  151 // Assertions around where items are added. |  | 
|  152 TEST_F(ShelfModelTest, AddIndices) { |  | 
|  153   // Insert browser short cut at index 1. |  | 
|  154   ShelfItem browser_shortcut; |  | 
|  155   browser_shortcut.type = TYPE_BROWSER_SHORTCUT; |  | 
|  156   int browser_shortcut_index = model_->Add(browser_shortcut); |  | 
|  157   EXPECT_EQ(1, browser_shortcut_index); |  | 
|  158  |  | 
|  159   // App items should be after the browser shortcut. |  | 
|  160   ShelfItem item; |  | 
|  161   item.type = TYPE_APP; |  | 
|  162   int platform_app_index1 = model_->Add(item); |  | 
|  163   EXPECT_EQ(2, platform_app_index1); |  | 
|  164  |  | 
|  165   // Add another platform app item, it should follow first. |  | 
|  166   int platform_app_index2 = model_->Add(item); |  | 
|  167   EXPECT_EQ(3, platform_app_index2); |  | 
|  168  |  | 
|  169   // APP_SHORTCUT priority is higher than PLATFORM_APP but same as |  | 
|  170   // BROWSER_SHORTCUT. So APP_SHORTCUT is located after BROWSER_SHORCUT. |  | 
|  171   item.type = TYPE_APP_SHORTCUT; |  | 
|  172   int app_shortcut_index1 = model_->Add(item); |  | 
|  173   EXPECT_EQ(2, app_shortcut_index1); |  | 
|  174  |  | 
|  175   item.type = TYPE_APP_SHORTCUT; |  | 
|  176   int app_shortcut_index2 = model_->Add(item); |  | 
|  177   EXPECT_EQ(3, app_shortcut_index2); |  | 
|  178  |  | 
|  179   // Check that AddAt() figures out the correct indexes for app shortcuts. |  | 
|  180   // APP_SHORTCUT and BROWSER_SHORTCUT has the same weight. |  | 
|  181   // So APP_SHORTCUT is located at index 0. And, BROWSER_SHORTCUT is located at |  | 
|  182   // index 1. |  | 
|  183   item.type = TYPE_APP_SHORTCUT; |  | 
|  184   int app_shortcut_index3 = model_->AddAt(1, item); |  | 
|  185   EXPECT_EQ(1, app_shortcut_index3); |  | 
|  186  |  | 
|  187   item.type = TYPE_APP_SHORTCUT; |  | 
|  188   int app_shortcut_index4 = model_->AddAt(6, item); |  | 
|  189   EXPECT_EQ(5, app_shortcut_index4); |  | 
|  190  |  | 
|  191   item.type = TYPE_APP_SHORTCUT; |  | 
|  192   int app_shortcut_index5 = model_->AddAt(3, item); |  | 
|  193   EXPECT_EQ(3, app_shortcut_index5); |  | 
|  194  |  | 
|  195   // Before there are any panels, no icons should be right aligned. |  | 
|  196   EXPECT_EQ(model_->item_count(), model_->FirstPanelIndex()); |  | 
|  197  |  | 
|  198   // Check that AddAt() figures out the correct indexes for apps and panels. |  | 
|  199   item.type = TYPE_APP; |  | 
|  200   int platform_app_index3 = model_->AddAt(3, item); |  | 
|  201   EXPECT_EQ(7, platform_app_index3); |  | 
|  202  |  | 
|  203   item.type = TYPE_APP_PANEL; |  | 
|  204   int app_panel_index1 = model_->AddAt(2, item); |  | 
|  205   EXPECT_EQ(10, app_panel_index1); |  | 
|  206  |  | 
|  207   item.type = TYPE_APP; |  | 
|  208   int platform_app_index4 = model_->AddAt(11, item); |  | 
|  209   EXPECT_EQ(10, platform_app_index4); |  | 
|  210  |  | 
|  211   item.type = TYPE_APP_PANEL; |  | 
|  212   int app_panel_index2 = model_->AddAt(12, item); |  | 
|  213   EXPECT_EQ(12, app_panel_index2); |  | 
|  214  |  | 
|  215   item.type = TYPE_APP; |  | 
|  216   int platform_app_index5 = model_->AddAt(7, item); |  | 
|  217   EXPECT_EQ(7, platform_app_index5); |  | 
|  218  |  | 
|  219   item.type = TYPE_APP_PANEL; |  | 
|  220   int app_panel_index3 = model_->AddAt(13, item); |  | 
|  221   EXPECT_EQ(13, app_panel_index3); |  | 
|  222  |  | 
|  223   // Right aligned index should be the first app panel index. |  | 
|  224   EXPECT_EQ(12, model_->FirstPanelIndex()); |  | 
|  225  |  | 
|  226   EXPECT_EQ(TYPE_BROWSER_SHORTCUT, model_->items()[2].type); |  | 
|  227   EXPECT_EQ(TYPE_APP_LIST, model_->items()[0].type); |  | 
|  228 } |  | 
|  229  |  | 
|  230 // Test that the indexes for the running applications are properly determined. |  | 
|  231 TEST_F(ShelfModelTest, FirstRunningAppIndex) { |  | 
|  232   // Insert the browser shortcut at index 1 and check that the running |  | 
|  233   // application index would be behind it. |  | 
|  234   ShelfItem item; |  | 
|  235   item.type = TYPE_BROWSER_SHORTCUT; |  | 
|  236   EXPECT_EQ(1, model_->Add(item)); |  | 
|  237   EXPECT_EQ(2, model_->FirstRunningAppIndex()); |  | 
|  238  |  | 
|  239   // Insert a panel application at the end and check that the running |  | 
|  240   // application index would be at / before the application panel. |  | 
|  241   item.type = TYPE_APP_PANEL; |  | 
|  242   EXPECT_EQ(2, model_->Add(item)); |  | 
|  243   EXPECT_EQ(2, model_->FirstRunningAppIndex()); |  | 
|  244  |  | 
|  245   // Insert an application shortcut and make sure that the running application |  | 
|  246   // index would be behind it. |  | 
|  247   item.type = TYPE_APP_SHORTCUT; |  | 
|  248   EXPECT_EQ(2, model_->Add(item)); |  | 
|  249   EXPECT_EQ(3, model_->FirstRunningAppIndex()); |  | 
|  250  |  | 
|  251   // Insert a two app items and check the first running app index. |  | 
|  252   item.type = TYPE_APP; |  | 
|  253   EXPECT_EQ(3, model_->Add(item)); |  | 
|  254   EXPECT_EQ(3, model_->FirstRunningAppIndex()); |  | 
|  255   EXPECT_EQ(4, model_->Add(item)); |  | 
|  256   EXPECT_EQ(3, model_->FirstRunningAppIndex()); |  | 
|  257 } |  | 
|  258  |  | 
|  259 // Assertions around id generation and usage. |  | 
|  260 TEST_F(ShelfModelTest, ShelfIDTests) { |  | 
|  261   // Get the next to use ID counter. |  | 
|  262   ShelfID id = model_->next_id(); |  | 
|  263  |  | 
|  264   // Calling this function multiple times does not change the returned ID. |  | 
|  265   EXPECT_EQ(model_->next_id(), id); |  | 
|  266  |  | 
|  267   // Check that when we reserve a value it will be the previously retrieved ID, |  | 
|  268   // but it will not change the item count and retrieving the next ID should |  | 
|  269   // produce something new. |  | 
|  270   EXPECT_EQ(model_->reserve_external_id(), id); |  | 
|  271   EXPECT_EQ(1, model_->item_count()); |  | 
|  272   ShelfID id2 = model_->next_id(); |  | 
|  273   EXPECT_NE(id2, id); |  | 
|  274  |  | 
|  275   // Adding another item to the list should also produce a new ID. |  | 
|  276   ShelfItem item; |  | 
|  277   item.type = TYPE_APP; |  | 
|  278   model_->Add(item); |  | 
|  279   EXPECT_NE(model_->next_id(), id2); |  | 
|  280 } |  | 
|  281  |  | 
|  282 // This verifies that converting an existing item into a lower weight category |  | 
|  283 // (e.g. shortcut to running but not pinned app) will move it to the proper |  | 
|  284 // location. See crbug.com/248769. |  | 
|  285 TEST_F(ShelfModelTest, CorrectMoveItemsWhenStateChange) { |  | 
|  286   // The first item is the app list and last item is the browser. |  | 
|  287   ShelfItem browser_shortcut; |  | 
|  288   browser_shortcut.type = TYPE_BROWSER_SHORTCUT; |  | 
|  289   int browser_shortcut_index = model_->Add(browser_shortcut); |  | 
|  290   EXPECT_EQ(TYPE_APP_LIST, model_->items()[0].type); |  | 
|  291   EXPECT_EQ(1, browser_shortcut_index); |  | 
|  292  |  | 
|  293   // Add three shortcuts. They should all be moved between the two. |  | 
|  294   ShelfItem item; |  | 
|  295   item.type = TYPE_APP_SHORTCUT; |  | 
|  296   int app1_index = model_->Add(item); |  | 
|  297   EXPECT_EQ(2, app1_index); |  | 
|  298   int app2_index = model_->Add(item); |  | 
|  299   EXPECT_EQ(3, app2_index); |  | 
|  300   int app3_index = model_->Add(item); |  | 
|  301   EXPECT_EQ(4, app3_index); |  | 
|  302  |  | 
|  303   // Now change the type of the second item and make sure that it is moving |  | 
|  304   // behind the shortcuts. |  | 
|  305   item.type = TYPE_APP; |  | 
|  306   model_->Set(app2_index, item); |  | 
|  307  |  | 
|  308   // The item should have moved in front of the app launcher. |  | 
|  309   EXPECT_EQ(TYPE_APP, model_->items()[4].type); |  | 
|  310 } |  | 
|  311  |  | 
|  312 }  // namespace ash |  | 
| OLD | NEW |