|  | // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 
|  | // Use of this source code is governed by a BSD-style license that can be | 
|  | // found in the LICENSE file. | 
|  |  | 
|  | #include "chrome/browser/ui/tabs/tab_menu_model.h" | 
|  |  | 
|  | #include "base/test/scoped_feature_list.h" | 
|  | #include "chrome/browser/ui/browser_commands.h" | 
|  | #include "chrome/browser/ui/tabs/existing_base_sub_menu_model.h" | 
|  | #include "chrome/browser/ui/ui_features.h" | 
|  | #include "chrome/test/base/browser_with_test_window_test.h" | 
|  | #include "chrome/test/base/menu_model_test.h" | 
|  | #include "testing/gtest/include/gtest/gtest.h" | 
|  | #include "ui/base/models/menu_model.h" | 
|  |  | 
|  | class TabMenuModelTest : public MenuModelTest, | 
|  | public BrowserWithTestWindowTest { | 
|  | }; | 
|  |  | 
|  | TEST_F(TabMenuModelTest, Basics) { | 
|  | chrome::NewTab(browser()); | 
|  | TabMenuModel model(&delegate_, browser()->tab_strip_model(), 0); | 
|  |  | 
|  | // Verify it has items. The number varies by platform, so we don't check | 
|  | // the exact number. | 
|  | EXPECT_GT(model.GetItemCount(), 5); | 
|  |  | 
|  | int item_count = 0; | 
|  | CountEnabledExecutable(&model, &item_count); | 
|  | EXPECT_GT(item_count, 0); | 
|  | EXPECT_EQ(item_count, delegate_.execute_count_); | 
|  | EXPECT_EQ(item_count, delegate_.enable_count_); | 
|  | } | 
|  |  | 
|  | TEST_F(TabMenuModelTest, MoveToNewWindow) { | 
|  | chrome::NewTab(browser()); | 
|  | TabMenuModel model(&delegate_, browser()->tab_strip_model(), 0); | 
|  |  | 
|  | // Verify that CommandMoveTabsToNewWindow is in the menu. | 
|  | EXPECT_GT( | 
|  | model.GetIndexOfCommandId(TabStripModel::CommandMoveTabsToNewWindow), -1); | 
|  | } | 
|  |  | 
|  | TEST_F(TabMenuModelTest, AddToExistingGroupSubmenu) { | 
|  | chrome::NewTab(browser()); | 
|  | chrome::NewTab(browser()); | 
|  | chrome::NewTab(browser()); | 
|  | chrome::NewTab(browser()); | 
|  |  | 
|  | TabStripModel* tab_strip_model = browser()->tab_strip_model(); | 
|  |  | 
|  | tab_strip_model->AddToNewGroup({0}); | 
|  | tab_strip_model->AddToNewGroup({1}); | 
|  | tab_strip_model->AddToNewGroup({2}); | 
|  |  | 
|  | TabMenuModel menu(&delegate_, tab_strip_model, 3); | 
|  |  | 
|  | int submenu_index = | 
|  | menu.GetIndexOfCommandId(TabStripModel::CommandAddToExistingGroup); | 
|  | ui::MenuModel* submenu = menu.GetSubmenuModelAt(submenu_index); | 
|  |  | 
|  | EXPECT_TRUE(submenu->HasIcons()); | 
|  | EXPECT_EQ(submenu->GetItemCount(), 5); | 
|  | EXPECT_EQ(submenu->GetCommandIdAt(0), | 
|  | ExistingBaseSubMenuModel::kMinExistingTabGroupCommandId); | 
|  | EXPECT_EQ(submenu->GetTypeAt(1), ui::MenuModel::TYPE_SEPARATOR); | 
|  | EXPECT_EQ(submenu->GetCommandIdAt(2), | 
|  | ExistingBaseSubMenuModel::kMinExistingTabGroupCommandId + 1); | 
|  | EXPECT_EQ(submenu->GetCommandIdAt(3), | 
|  | ExistingBaseSubMenuModel::kMinExistingTabGroupCommandId + 2); | 
|  | EXPECT_EQ(submenu->GetCommandIdAt(4), | 
|  | ExistingBaseSubMenuModel::kMinExistingTabGroupCommandId + 3); | 
|  | } | 
|  |  | 
|  | TEST_F(TabMenuModelTest, AddToExistingGroupSubmenu_DoesNotIncludeCurrentGroup) { | 
|  | chrome::NewTab(browser()); | 
|  | chrome::NewTab(browser()); | 
|  | chrome::NewTab(browser()); | 
|  | chrome::NewTab(browser()); | 
|  |  | 
|  | TabStripModel* tab_strip_model = browser()->tab_strip_model(); | 
|  |  | 
|  | tab_strip_model->AddToNewGroup({0}); | 
|  | tab_strip_model->AddToNewGroup({1}); | 
|  | tab_strip_model->AddToNewGroup({2}); | 
|  |  | 
|  | TabMenuModel menu(&delegate_, tab_strip_model, 1); | 
|  |  | 
|  | int submenu_index = | 
|  | menu.GetIndexOfCommandId(TabStripModel::CommandAddToExistingGroup); | 
|  | ui::MenuModel* submenu = menu.GetSubmenuModelAt(submenu_index); | 
|  |  | 
|  | EXPECT_TRUE(submenu->HasIcons()); | 
|  | EXPECT_EQ(submenu->GetItemCount(), 4); | 
|  | EXPECT_EQ(submenu->GetCommandIdAt(0), | 
|  | ExistingBaseSubMenuModel::kMinExistingTabGroupCommandId); | 
|  | EXPECT_EQ(submenu->GetTypeAt(1), ui::MenuModel::TYPE_SEPARATOR); | 
|  | EXPECT_EQ(submenu->GetCommandIdAt(2), | 
|  | ExistingBaseSubMenuModel::kMinExistingTabGroupCommandId + 1); | 
|  | EXPECT_EQ(submenu->GetCommandIdAt(3), | 
|  | ExistingBaseSubMenuModel::kMinExistingTabGroupCommandId + 2); | 
|  | } | 
|  |  | 
|  | // In some cases, groups may change after the menu is created. For example an | 
|  | // extension may modify groups while the menu is open. If a group referenced in | 
|  | // the menu goes away, ensure we handle this gracefully. | 
|  | // | 
|  | // Regression test for crbug.com/1197875 | 
|  | TEST_F(TabMenuModelTest, AddToExistingGroupAfterGroupDestroyed) { | 
|  | chrome::NewTab(browser()); | 
|  | chrome::NewTab(browser()); | 
|  |  | 
|  | TabStripModel* tab_strip_model = browser()->tab_strip_model(); | 
|  | tab_strip_model->AddToNewGroup({0}); | 
|  |  | 
|  | TabMenuModel menu(&delegate_, tab_strip_model, 1); | 
|  |  | 
|  | int submenu_index = | 
|  | menu.GetIndexOfCommandId(TabStripModel::CommandAddToExistingGroup); | 
|  | ui::MenuModel* submenu = menu.GetSubmenuModelAt(submenu_index); | 
|  |  | 
|  | EXPECT_EQ(submenu->GetItemCount(), 3); | 
|  |  | 
|  | // Ungroup the tab at 0 to make the group in the menu dangle. | 
|  | tab_strip_model->RemoveFromGroup({0}); | 
|  |  | 
|  | // Try adding to the group from the menu. | 
|  | submenu->ActivatedAt(2); | 
|  |  | 
|  | EXPECT_FALSE(tab_strip_model->GetTabGroupForTab(0).has_value()); | 
|  | EXPECT_FALSE(tab_strip_model->GetTabGroupForTab(1).has_value()); | 
|  | } |