summaryrefslogtreecommitdiffstats
path: root/chrome/browser/cocoa/bookmark_menu_bridge_unittest.mm
diff options
context:
space:
mode:
Diffstat (limited to 'chrome/browser/cocoa/bookmark_menu_bridge_unittest.mm')
-rw-r--r--chrome/browser/cocoa/bookmark_menu_bridge_unittest.mm316
1 files changed, 316 insertions, 0 deletions
diff --git a/chrome/browser/cocoa/bookmark_menu_bridge_unittest.mm b/chrome/browser/cocoa/bookmark_menu_bridge_unittest.mm
new file mode 100644
index 0000000..47585aa
--- /dev/null
+++ b/chrome/browser/cocoa/bookmark_menu_bridge_unittest.mm
@@ -0,0 +1,316 @@
+// Copyright (c) 2009 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.
+
+#import <AppKit/AppKit.h>
+#import "base/scoped_nsobject.h"
+#include "base/string_util.h"
+#include "chrome/app/chrome_dll_resource.h"
+#include "chrome/browser/browser.h"
+#include "chrome/browser/cocoa/bookmark_menu_bridge.h"
+#include "chrome/browser/cocoa/browser_test_helper.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "testing/platform_test.h"
+
+class TestBookmarkMenuBridge : public BookmarkMenuBridge {
+ public:
+ TestBookmarkMenuBridge(Profile* profile)
+ : BookmarkMenuBridge(profile),
+ menu_([[NSMenu alloc] initWithTitle:@"test"]) {
+ }
+ virtual ~TestBookmarkMenuBridge() {}
+
+ scoped_nsobject<NSMenu> menu_;
+
+ protected:
+ // Overridden from BookmarkMenuBridge.
+ virtual NSMenu* BookmarkMenu() {
+ return menu_;
+ }
+};
+
+// TODO(jrg): see refactor comment in bookmark_bar_state_controller_unittest.mm
+class BookmarkMenuBridgeTest : public PlatformTest {
+ public:
+
+ void SetUp() {
+ bridge_.reset(new TestBookmarkMenuBridge(browser_test_helper_.profile()));
+ EXPECT_TRUE(bridge_.get());
+ }
+
+ // We are a friend of BookmarkMenuBridge (and have access to
+ // protected methods), but none of the classes generated by TEST_F()
+ // are. This (and AddNodeToMenu()) are simple wrappers to let
+ // derived test classes have access to protected methods.
+ void ClearBookmarkMenu(BookmarkMenuBridge* bridge, NSMenu* menu) {
+ bridge->ClearBookmarkMenu(menu);
+ }
+
+ void InvalidateMenu() { bridge_->InvalidateMenu(); }
+ bool menu_is_valid() { return bridge_->menuIsValid_; }
+
+ void AddNodeToMenu(BookmarkMenuBridge* bridge, const BookmarkNode* root,
+ NSMenu* menu) {
+ bridge->AddNodeToMenu(root, menu);
+ }
+
+ NSMenuItem* MenuItemForNode(BookmarkMenuBridge* bridge,
+ const BookmarkNode* node) {
+ return bridge->MenuItemForNode(node);
+ }
+
+ NSMenuItem* AddItemToMenu(NSMenu *menu, NSString *title, SEL selector) {
+ NSMenuItem *item = [[[NSMenuItem alloc] initWithTitle:title action:NULL
+ keyEquivalent:@""] autorelease];
+ if (selector)
+ [item setAction:selector];
+ [menu addItem:item];
+ return item;
+ }
+
+ BrowserTestHelper browser_test_helper_;
+ scoped_ptr<TestBookmarkMenuBridge> bridge_;
+};
+
+TEST_F(BookmarkMenuBridgeTest, TestBookmarkMenuAutoSeparator) {
+ BookmarkModel* model = bridge_->GetBookmarkModel();
+ bridge_->Loaded(model);
+ NSMenu* menu = bridge_->menu_.get();
+ bridge_->UpdateMenu(menu);
+ // The bare menu after loading has a separator and an "Other Bookmarks"
+ // submenu.
+ EXPECT_EQ(2, [menu numberOfItems]);
+ // Add a bookmark and reload and there should be 4 items: the previous
+ // menu contents plus a new separator and the new bookmark.
+ const BookmarkNode* parent = model->GetBookmarkBarNode();
+ const char* url = "http://www.zim-bop-a-dee.com/";
+ std::wstring title(L"Bookmark");
+ model->AddURL(parent, 0, title, GURL(url));
+ bridge_->UpdateMenu(menu);
+ EXPECT_EQ(4, [menu numberOfItems]);
+ // Remove the new bookmark and reload and we should have 2 items again
+ // because the separator should have been removed as well.
+ model->Remove(parent, 0);
+ bridge_->UpdateMenu(menu);
+ EXPECT_EQ(2, [menu numberOfItems]);
+}
+
+// Test that ClearBookmarkMenu() removes all bookmark menus.
+TEST_F(BookmarkMenuBridgeTest, TestClearBookmarkMenu) {
+ NSMenu* menu = bridge_->menu_.get();
+
+ AddItemToMenu(menu, @"hi mom", nil);
+ AddItemToMenu(menu, @"not", @selector(openBookmarkMenuItem:));
+ NSMenuItem* item = AddItemToMenu(menu, @"hi mom", nil);
+ [item setSubmenu:[[[NSMenu alloc] initWithTitle:@"bar"] autorelease]];
+ AddItemToMenu(menu, @"not", @selector(openBookmarkMenuItem:));
+ AddItemToMenu(menu, @"zippy", @selector(length));
+ [menu addItem:[NSMenuItem separatorItem]];
+
+ ClearBookmarkMenu(bridge_.get(), menu);
+
+ // Make sure all bookmark items are removed, all items with
+ // submenus removed, and all separator items are gone.
+ EXPECT_EQ(2, [menu numberOfItems]);
+ for (NSMenuItem *item in [menu itemArray]) {
+ EXPECT_FALSE([[item title] isEqual:@"not"]);
+ }
+}
+
+// Test invalidation
+TEST_F(BookmarkMenuBridgeTest, TestInvalidation) {
+ BookmarkModel* model = bridge_->GetBookmarkModel();
+ bridge_->Loaded(model);
+
+ EXPECT_FALSE(menu_is_valid());
+ bridge_->UpdateMenu(bridge_->menu_);
+ EXPECT_TRUE(menu_is_valid());
+
+ InvalidateMenu();
+ EXPECT_FALSE(menu_is_valid());
+ InvalidateMenu();
+ EXPECT_FALSE(menu_is_valid());
+ bridge_->UpdateMenu(bridge_->menu_);
+ EXPECT_TRUE(menu_is_valid());
+ bridge_->UpdateMenu(bridge_->menu_);
+ EXPECT_TRUE(menu_is_valid());
+
+ const BookmarkNode* parent = model->GetBookmarkBarNode();
+ const char* url = "http://www.zim-bop-a-dee.com/";
+ std::wstring title(L"Bookmark");
+ model->AddURL(parent, 0, title, GURL(url));
+
+ EXPECT_FALSE(menu_is_valid());
+ bridge_->UpdateMenu(bridge_->menu_);
+ EXPECT_TRUE(menu_is_valid());
+}
+
+// Test that AddNodeToMenu() properly adds bookmark nodes as menus,
+// including the recursive case.
+TEST_F(BookmarkMenuBridgeTest, TestAddNodeToMenu) {
+ std::wstring empty;
+ NSMenu* menu = bridge_->menu_.get();
+
+ BookmarkModel* model = bridge_->GetBookmarkModel();
+ const BookmarkNode* root = model->GetBookmarkBarNode();
+ EXPECT_TRUE(model && root);
+
+ const char* short_url = "http://foo/";
+ const char* long_url = "http://super-duper-long-url--."
+ "that.cannot.possibly.fit.even-in-80-columns"
+ "or.be.reasonably-displayed-in-a-menu"
+ "without.looking-ridiculous.com/"; // 140 chars total
+
+ // 3 nodes; middle one has a child, last one has a HUGE URL
+ // Set their titles to be the same as the URLs
+ const BookmarkNode* node = NULL;
+ model->AddURL(root, 0, ASCIIToWide(short_url), GURL(short_url));
+ bridge_->UpdateMenu(menu);
+ int prev_count = [menu numberOfItems] - 1; // "extras" added at this point
+ node = model->AddGroup(root, 1, empty);
+ model->AddURL(root, 2, ASCIIToWide(long_url), GURL(long_url));
+
+ // And the submenu fo the middle one
+ model->AddURL(node, 0, empty, GURL("http://sub"));
+ bridge_->UpdateMenu(menu);
+
+ EXPECT_EQ((NSInteger)(prev_count+3), [menu numberOfItems]);
+
+ // Verify the 1st one is there with the right action.
+ NSMenuItem* item = [menu itemWithTitle:[NSString
+ stringWithUTF8String:short_url]];
+ EXPECT_TRUE(item);
+ EXPECT_EQ(@selector(openBookmarkMenuItem:), [item action]);
+ EXPECT_EQ(NO, [item hasSubmenu]);
+ NSMenuItem* short_item = item;
+ NSMenuItem* long_item = nil;
+
+ // Now confirm we have 2 submenus (the one we added, plus "other")
+ int subs = 0;
+ for (item in [menu itemArray]) {
+ if ([item hasSubmenu])
+ subs++;
+ }
+ EXPECT_EQ(2, subs);
+
+ for (item in [menu itemArray]) {
+ if ([[item title] hasPrefix:@"http://super-duper"]) {
+ long_item = item;
+ break;
+ }
+ }
+ EXPECT_TRUE(long_item);
+
+ // Make sure a short title looks fine
+ NSString* s = [short_item title];
+ EXPECT_TRUE([s isEqual:[NSString stringWithUTF8String:short_url]]);
+
+ // Make sure a super-long title gets trimmed
+ s = [long_item title];
+ EXPECT_TRUE([s length] < strlen(long_url));
+
+ // Confirm tooltips and confirm they are not trimmed (like the item
+ // name might be). Add tolerance for URL fixer-upping;
+ // e.g. http://foo becomes http://foo/)
+ EXPECT_GE([[short_item toolTip] length], (2*strlen(short_url) - 5));
+ EXPECT_GE([[long_item toolTip] length], (2*strlen(long_url) - 5));
+
+ // Make sure the favicon is non-nil (should be either the default site
+ // icon or a favicon, if present).
+ EXPECT_TRUE([short_item image]);
+ EXPECT_TRUE([long_item image]);
+}
+
+// Makes sure our internal map of BookmarkNode to NSMenuItem works.
+TEST_F(BookmarkMenuBridgeTest, TestGetMenuItemForNode) {
+ std::wstring empty;
+ NSMenu* menu = bridge_->menu_.get();
+
+ BookmarkModel* model = bridge_->GetBookmarkModel();
+ const BookmarkNode* bookmark_bar = model->GetBookmarkBarNode();
+ const BookmarkNode* root = model->AddGroup(bookmark_bar, 0, empty);
+ EXPECT_TRUE(model && root);
+
+ model->AddURL(root, 0, ASCIIToWide("Test Item"), GURL("http://test"));
+ AddNodeToMenu(bridge_.get(), root, menu);
+ EXPECT_TRUE(MenuItemForNode(bridge_.get(), root->GetChild(0)));
+
+ model->AddURL(root, 1, ASCIIToWide("Test 2"), GURL("http://second-test"));
+ AddNodeToMenu(bridge_.get(), root, menu);
+ EXPECT_TRUE(MenuItemForNode(bridge_.get(), root->GetChild(0)));
+ EXPECT_TRUE(MenuItemForNode(bridge_.get(), root->GetChild(1)));
+
+ const BookmarkNode* removed_node = root->GetChild(0);
+ EXPECT_EQ(2, root->GetChildCount());
+ model->Remove(root, 0);
+ EXPECT_EQ(1, root->GetChildCount());
+ bridge_->UpdateMenu(menu);
+ EXPECT_FALSE(MenuItemForNode(bridge_.get(), removed_node));
+ EXPECT_TRUE(MenuItemForNode(bridge_.get(), root->GetChild(0)));
+
+ const BookmarkNode empty_node(GURL("http://no-where/"));
+ EXPECT_FALSE(MenuItemForNode(bridge_.get(), &empty_node));
+ EXPECT_FALSE(MenuItemForNode(bridge_.get(), NULL));
+}
+
+// Test that Loaded() adds both the bookmark bar nodes and the "other" nodes.
+TEST_F(BookmarkMenuBridgeTest, TestAddNodeToOther) {
+ std::wstring empty;
+ NSMenu* menu = bridge_->menu_.get();
+
+ BookmarkModel* model = bridge_->GetBookmarkModel();
+ const BookmarkNode* root = model->other_node();
+ EXPECT_TRUE(model && root);
+
+ const char* short_url = "http://foo/";
+ model->AddURL(root, 0, ASCIIToWide(short_url), GURL(short_url));
+
+ bridge_->UpdateMenu(menu);
+ ASSERT_GT([menu numberOfItems], 0);
+ NSMenuItem* other = [menu itemAtIndex:([menu numberOfItems]-1)];
+ EXPECT_TRUE(other);
+ EXPECT_TRUE([other hasSubmenu]);
+ ASSERT_GT([[other submenu] numberOfItems], 0);
+ EXPECT_TRUE([[[[other submenu] itemAtIndex:0] title] isEqual:@"http://foo/"]);
+}
+
+TEST_F(BookmarkMenuBridgeTest, TestFavIconLoading) {
+ std::wstring empty;
+ NSMenu* menu = bridge_->menu_;
+
+ BookmarkModel* model = bridge_->GetBookmarkModel();
+ const BookmarkNode* root = model->GetBookmarkBarNode();
+ EXPECT_TRUE(model && root);
+
+ const BookmarkNode* node =
+ model->AddURL(root, 0, ASCIIToWide("Test Item"),
+ GURL("http://favicon-test"));
+ bridge_->UpdateMenu(menu);
+ NSMenuItem* item = [menu itemWithTitle:@"Test Item"];
+ EXPECT_TRUE([item image]);
+ [item setImage:nil];
+ bridge_->BookmarkNodeFavIconLoaded(model, node);
+ EXPECT_TRUE([item image]);
+}
+
+TEST_F(BookmarkMenuBridgeTest, TestChangeTitle) {
+ NSMenu* menu = bridge_->menu_;
+ BookmarkModel* model = bridge_->GetBookmarkModel();
+ const BookmarkNode* root = model->GetBookmarkBarNode();
+ EXPECT_TRUE(model && root);
+
+ const BookmarkNode* node =
+ model->AddURL(root, 0, L"Test Item",
+ GURL("http://title-test"));
+ bridge_->UpdateMenu(menu);
+ NSMenuItem* item = [menu itemWithTitle:@"Test Item"];
+ EXPECT_TRUE([item image]);
+
+ model->SetTitle(node, L"New Title");
+
+ item = [menu itemWithTitle:@"Test Item"];
+ EXPECT_FALSE(item);
+ item = [menu itemWithTitle:@"New Title"];
+ EXPECT_TRUE(item);
+}
+