// 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 #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" // TODO(jrg): see refactor comment in bookmark_bar_state_controller_unittest.mm class BookmarkMenuBridgeTest : public testing::Test { public: // 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 AddNodeToMenu(BookmarkMenuBridge* bridge, const BookmarkNode* root, NSMenu* menu) { bridge->AddNodeToMenu(root, menu); } 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_; }; // Test that ClearBookmarkMenu() removes all bookmark menus. TEST_F(BookmarkMenuBridgeTest, TestClearBookmarkMenu) { scoped_ptr bridge(new BookmarkMenuBridge()); EXPECT_TRUE(bridge.get()); NSMenu* menu = [[[NSMenu alloc] initWithTitle:@"foo"] autorelease]; 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)); ClearBookmarkMenu(bridge.get(), menu); // Make sure all bookmark items are removed, and all items with // submenus removed. EXPECT_EQ(2, [menu numberOfItems]); for (NSMenuItem *item in [menu itemArray]) { EXPECT_FALSE([[item title] isEqual:@"not"]); } } // Test that AddNodeToMenu() properly adds bookmark nodes as menus, // including the recursive case. TEST_F(BookmarkMenuBridgeTest, TestAddNodeToMenu) { std::wstring empty; Profile* profile = browser_test_helper_.profile(); scoped_ptr bridge(new BookmarkMenuBridge()); EXPECT_TRUE(bridge.get()); NSMenu* menu = [[[NSMenu alloc] initWithTitle:@"foo"] autorelease]; BookmarkModel* model = profile->GetBookmarkModel(); const BookmarkNode* bookmark_bar = model->GetBookmarkBarNode(); const BookmarkNode* root = model->AddGroup(bookmark_bar, 0, empty); 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)); 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")); // Add to the NSMenu, then confirm it looks good AddNodeToMenu(bridge.get(), root, menu); EXPECT_EQ(3, [menu numberOfItems]); // Confirm for just the first and last (index 0 and 2) for (int x=0; x<3; x+=2) { EXPECT_EQ(@selector(openBookmarkMenuItem:), [[menu itemAtIndex:x] action]); EXPECT_EQ(NO, [[menu itemAtIndex:x] hasSubmenu]); } // Now confirm the middle one (index 1) NSMenuItem* middle = [menu itemAtIndex:1]; EXPECT_NE(NO, [middle hasSubmenu]); EXPECT_EQ(1, [[middle submenu] numberOfItems]); // Confirm 1st and 3rd item have the same action (that we specified). // Make sure the submenu item does NOT have an bookmark action. EXPECT_EQ([[menu itemAtIndex:0] action], [[menu itemAtIndex:2] action]); EXPECT_NE([[menu itemAtIndex:0] action], [[menu itemAtIndex:1] action]); // Make sure a short title looks fine NSString* s = [[menu itemAtIndex:0] title]; EXPECT_TRUE([s isEqual:[NSString stringWithUTF8String:short_url]]); // Make sure a super-long title gets trimmed s = [[menu itemAtIndex:0] 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([[[menu itemAtIndex:0] toolTip] length], (2*strlen(short_url) - 5)); EXPECT_GE([[[menu itemAtIndex:2] toolTip] length], (2*strlen(long_url) - 5)); }