bookmark_menu_delegate_unittest.cc revision 5d1f7b1de12d16ceb2c938c56701a3e8bfa558f7
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 "chrome/browser/ui/views/bookmarks/bookmark_menu_delegate.h"
6
7#include "base/strings/utf_string_conversions.h"
8#include "chrome/browser/bookmarks/bookmark_model.h"
9#include "chrome/browser/bookmarks/bookmark_model_factory.h"
10#include "chrome/browser/bookmarks/bookmark_stats.h"
11#include "chrome/browser/bookmarks/bookmark_test_helpers.h"
12#include "chrome/browser/profiles/profile.h"
13#include "chrome/test/base/browser_with_test_window_test.h"
14#include "chrome/test/base/testing_profile.h"
15#include "ui/views/controls/menu/menu_runner.h"
16#include "ui/views/controls/menu/submenu_view.h"
17
18using base::ASCIIToUTF16;
19
20class BookmarkMenuDelegateTest : public BrowserWithTestWindowTest {
21 public:
22  BookmarkMenuDelegateTest() : model_(NULL) {}
23
24  virtual void SetUp() OVERRIDE {
25    BrowserWithTestWindowTest::SetUp();
26
27    profile()->CreateBookmarkModel(true);
28
29    model_ = BookmarkModelFactory::GetForProfile(profile());
30    test::WaitForBookmarkModelToLoad(model_);
31
32    AddTestData();
33  }
34
35  virtual void TearDown() OVERRIDE {
36    if (bookmark_menu_delegate_.get()) {
37      // Since we never show the menu we need to pass the MenuItemView to
38      // MenuRunner so that the MenuItemView is destroyed.
39      views::MenuRunner menu_runner(bookmark_menu_delegate_->menu());
40      bookmark_menu_delegate_.reset();
41    }
42    BrowserWithTestWindowTest::TearDown();
43  }
44
45 protected:
46  void NewDelegate(int min_menu_id, int max_menu_id) {
47    // Destroy current menu if available, see comments in TearDown().
48    if (bookmark_menu_delegate_.get())
49      views::MenuRunner menu_runner(bookmark_menu_delegate_->menu());
50
51    bookmark_menu_delegate_.reset(
52        new BookmarkMenuDelegate(browser(), NULL, NULL,
53                                 min_menu_id, max_menu_id));
54  }
55
56  void NewAndInitDelegateForPermanent(int min_menu_id,
57                                      int max_menu_id) {
58    const BookmarkNode* node = model_->bookmark_bar_node();
59    NewDelegate(min_menu_id, max_menu_id);
60    bookmark_menu_delegate_->Init(&test_delegate_, NULL, node, 0,
61                                  BookmarkMenuDelegate::SHOW_PERMANENT_FOLDERS,
62                                  BOOKMARK_LAUNCH_LOCATION_NONE);
63  }
64
65  BookmarkModel* model_;
66
67  scoped_ptr<BookmarkMenuDelegate> bookmark_menu_delegate_;
68
69 private:
70  std::string base_path() const { return "file:///c:/tmp/"; }
71
72  // Creates the following structure:
73  // bookmark bar node
74  //   a
75  //   F1
76  //    f1a
77  //    F11
78  //     f11a
79  //   F2
80  // other node
81  //   oa
82  //   OF1
83  //     of1a
84  void AddTestData() {
85    const BookmarkNode* bb_node = model_->bookmark_bar_node();
86    std::string test_base = base_path();
87    model_->AddURL(bb_node, 0, ASCIIToUTF16("a"), GURL(test_base + "a"));
88    const BookmarkNode* f1 = model_->AddFolder(bb_node, 1, ASCIIToUTF16("F1"));
89    model_->AddURL(f1, 0, ASCIIToUTF16("f1a"), GURL(test_base + "f1a"));
90    const BookmarkNode* f11 = model_->AddFolder(f1, 1, ASCIIToUTF16("F11"));
91    model_->AddURL(f11, 0, ASCIIToUTF16("f11a"), GURL(test_base + "f11a"));
92    model_->AddFolder(bb_node, 2, ASCIIToUTF16("F2"));
93
94    // Children of the other node.
95    model_->AddURL(model_->other_node(), 0, ASCIIToUTF16("oa"),
96                   GURL(test_base + "oa"));
97    const BookmarkNode* of1 =
98        model_->AddFolder(model_->other_node(), 1, ASCIIToUTF16("OF1"));
99    model_->AddURL(of1, 0, ASCIIToUTF16("of1a"), GURL(test_base + "of1a"));
100  }
101
102  views::MenuDelegate test_delegate_;
103
104  DISALLOW_COPY_AND_ASSIGN(BookmarkMenuDelegateTest);
105};
106
107// Verifies WillRemoveBookmarks() doesn't attempt to access MenuItemViews that
108// have since been deleted.
109TEST_F(BookmarkMenuDelegateTest, RemoveBookmarks) {
110  views::MenuDelegate test_delegate;
111  const BookmarkNode* node = model_->bookmark_bar_node()->GetChild(1);
112  NewDelegate(0, kint32max);
113  bookmark_menu_delegate_->Init(&test_delegate, NULL, node, 0,
114                                BookmarkMenuDelegate::HIDE_PERMANENT_FOLDERS,
115                                BOOKMARK_LAUNCH_LOCATION_NONE);
116  std::vector<const BookmarkNode*> nodes_to_remove;
117  nodes_to_remove.push_back(node->GetChild(1));
118  bookmark_menu_delegate_->WillRemoveBookmarks(nodes_to_remove);
119  nodes_to_remove.clear();
120  bookmark_menu_delegate_->DidRemoveBookmarks();
121}
122
123// Verifies menu ID's of items in menu fall within the specified range.
124TEST_F(BookmarkMenuDelegateTest, MenuIdRange) {
125  // Start with maximum menu Id of 10 - the number of items that AddTestData()
126  // populated.  Everything should be created.
127  NewAndInitDelegateForPermanent(0, 10);
128  views::MenuItemView* root_item = bookmark_menu_delegate_->menu();
129  ASSERT_TRUE(root_item->HasSubmenu());
130  EXPECT_EQ(4, root_item->GetSubmenu()->GetMenuItemCount());
131  EXPECT_EQ(5, root_item->GetSubmenu()->child_count());  // Includes separator.
132  views::MenuItemView* F1_item = root_item->GetSubmenu()->GetMenuItemAt(1);
133  ASSERT_TRUE(F1_item->HasSubmenu());
134  EXPECT_EQ(2, F1_item->GetSubmenu()->GetMenuItemCount());
135  views::MenuItemView* F11_item = F1_item->GetSubmenu()->GetMenuItemAt(1);
136  ASSERT_TRUE(F11_item->HasSubmenu());
137  EXPECT_EQ(1, F11_item->GetSubmenu()->GetMenuItemCount());
138  views::MenuItemView* other_item = root_item->GetSubmenu()->GetMenuItemAt(3);
139  ASSERT_TRUE(other_item->HasSubmenu());
140  EXPECT_EQ(2, other_item->GetSubmenu()->GetMenuItemCount());
141  views::MenuItemView* OF1_item = other_item->GetSubmenu()->GetMenuItemAt(1);
142  ASSERT_TRUE(OF1_item->HasSubmenu());
143  EXPECT_EQ(1, OF1_item->GetSubmenu()->GetMenuItemCount());
144
145  // Reduce maximum 9.  "of1a" item should not be created.
146  NewAndInitDelegateForPermanent(0, 9);
147  root_item = bookmark_menu_delegate_->menu();
148  EXPECT_EQ(4, root_item->GetSubmenu()->GetMenuItemCount());
149  EXPECT_EQ(5, root_item->GetSubmenu()->child_count());  // Includes separator.
150  other_item = root_item->GetSubmenu()->GetMenuItemAt(3);
151  OF1_item = other_item->GetSubmenu()->GetMenuItemAt(1);
152  EXPECT_EQ(0, OF1_item->GetSubmenu()->GetMenuItemCount());
153
154  // Reduce maximum 8.  "OF1" submenu should not be created.
155  NewAndInitDelegateForPermanent(0, 8);
156  root_item = bookmark_menu_delegate_->menu();
157  EXPECT_EQ(4, root_item->GetSubmenu()->GetMenuItemCount());
158  EXPECT_EQ(5, root_item->GetSubmenu()->child_count());  // Includes separator.
159  other_item = root_item->GetSubmenu()->GetMenuItemAt(3);
160  EXPECT_EQ(1, other_item->GetSubmenu()->GetMenuItemCount());
161
162  // Reduce maximum 7.  "Other" submenu should be empty.
163  NewAndInitDelegateForPermanent(0, 7);
164  root_item = bookmark_menu_delegate_->menu();
165  EXPECT_EQ(4, root_item->GetSubmenu()->GetMenuItemCount());
166  EXPECT_EQ(5, root_item->GetSubmenu()->child_count());  // Includes separator.
167  other_item = root_item->GetSubmenu()->GetMenuItemAt(3);
168  EXPECT_EQ(0, other_item->GetSubmenu()->GetMenuItemCount());
169
170  // Reduce maximum to 6.  "Other" submenu should not be created, and no
171  // separator.
172  NewAndInitDelegateForPermanent(0, 6);
173  root_item = bookmark_menu_delegate_->menu();
174  EXPECT_EQ(3, root_item->GetSubmenu()->GetMenuItemCount());
175  EXPECT_EQ(3, root_item->GetSubmenu()->child_count());  // No separator.
176
177  // Reduce maximum 5.  "F2" and "Other" submenus shouldn't be created.
178  NewAndInitDelegateForPermanent(0, 5);
179  root_item = bookmark_menu_delegate_->menu();
180  EXPECT_EQ(2, root_item->GetSubmenu()->GetMenuItemCount());
181  EXPECT_EQ(2, root_item->GetSubmenu()->child_count());  // No separator.
182  F1_item = root_item->GetSubmenu()->GetMenuItemAt(1);
183  F11_item = F1_item->GetSubmenu()->GetMenuItemAt(1);
184  EXPECT_EQ(1, F11_item->GetSubmenu()->GetMenuItemCount());
185
186  // Reduce maximum to 4.  "f11a" item and "F2" and "Other" submenus should
187  // not be created.
188  NewAndInitDelegateForPermanent(0, 4);
189  root_item = bookmark_menu_delegate_->menu();
190  EXPECT_EQ(2, root_item->GetSubmenu()->GetMenuItemCount());
191  EXPECT_EQ(2, root_item->GetSubmenu()->child_count());  // No separator.
192  F1_item = root_item->GetSubmenu()->GetMenuItemAt(1);
193  F11_item = F1_item->GetSubmenu()->GetMenuItemAt(1);
194  EXPECT_EQ(0, F11_item->GetSubmenu()->GetMenuItemCount());
195
196  // Reduce maximum to 3.  "F11", "F2" and "Other" submenus should not be
197  // created.
198  NewAndInitDelegateForPermanent(0, 3);
199  root_item = bookmark_menu_delegate_->menu();
200  EXPECT_EQ(2, root_item->GetSubmenu()->GetMenuItemCount());
201  EXPECT_EQ(2, root_item->GetSubmenu()->child_count());  // No separator.
202  F1_item = root_item->GetSubmenu()->GetMenuItemAt(1);
203  EXPECT_EQ(views::MenuItemView::SUBMENU, F1_item->GetType());
204  EXPECT_EQ(1, F1_item->GetSubmenu()->GetMenuItemCount());
205
206  // Reduce maximum 2.  Only "a" item and empty "F1" submenu should be created.
207  NewAndInitDelegateForPermanent(0, 2);
208  root_item = bookmark_menu_delegate_->menu();
209  EXPECT_EQ(2, root_item->GetSubmenu()->GetMenuItemCount());
210  EXPECT_EQ(2, root_item->GetSubmenu()->child_count());  // No separator.
211  F1_item = root_item->GetSubmenu()->GetMenuItemAt(1);
212  EXPECT_EQ(views::MenuItemView::SUBMENU, F1_item->GetType());
213  EXPECT_EQ(0, F1_item->GetSubmenu()->GetMenuItemCount());
214
215  // Reduce maximum to 1.  Only "a" item should be created.
216  NewAndInitDelegateForPermanent(0, 1);
217  root_item = bookmark_menu_delegate_->menu();
218  EXPECT_EQ(1, root_item->GetSubmenu()->GetMenuItemCount());
219  EXPECT_EQ(1, root_item->GetSubmenu()->child_count());  // No separator.
220
221  // Verify correct handling of integer overflow with range, set kint32max as
222  // maximum and 1 less as minimum.  Only "a" item should be created.
223  NewAndInitDelegateForPermanent(kint32max - 1, kint32max);
224  root_item = bookmark_menu_delegate_->menu();
225  EXPECT_EQ(1, root_item->GetSubmenu()->GetMenuItemCount());
226  EXPECT_EQ(1, root_item->GetSubmenu()->child_count());  // No separator.
227}
228