Index: chrome/browser/ui/cocoa/bookmarks/bookmark_bar_folder_controller_unittest.mm |
diff --git a/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_folder_controller_unittest.mm b/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_folder_controller_unittest.mm |
index 3c2df2b069b85e44449f3b6ad1ac3fdc00e7803e..8a52dd2ccc02ae1bf863f3b3802d6f7b6d90fe5c 100644 |
--- a/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_folder_controller_unittest.mm |
+++ b/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_folder_controller_unittest.mm |
@@ -8,11 +8,11 @@ |
#include "base/memory/scoped_nsobject.h" |
#include "base/utf_string_conversions.h" |
#include "chrome/browser/bookmarks/bookmark_model.h" |
+#import "chrome/browser/ui/cocoa/animation_utils.h" |
#import "chrome/browser/ui/cocoa/bookmarks/bookmark_bar_constants.h" |
#import "chrome/browser/ui/cocoa/bookmarks/bookmark_bar_controller.h" |
+#import "chrome/browser/ui/cocoa/bookmarks/bookmark_bar_folder_button_cell.h" |
#import "chrome/browser/ui/cocoa/bookmarks/bookmark_bar_folder_controller.h" |
-#import "chrome/browser/ui/cocoa/bookmarks/bookmark_button_cell.h" |
-#include "chrome/browser/ui/cocoa/bookmarks/bookmark_menu_bridge.h" |
#import "chrome/browser/ui/cocoa/bookmarks/bookmark_bar_unittest_helper.h" |
#include "chrome/browser/ui/cocoa/cocoa_profile_test.h" |
#import "chrome/browser/ui/cocoa/cocoa_test_helper.h" |
@@ -22,164 +22,1550 @@ |
#import "testing/gtest_mac.h" |
#include "testing/platform_test.h" |
+// Add a redirect to make testing easier. |
+@interface BookmarkBarFolderController(MakeTestingEasier) |
+- (IBAction)openBookmarkFolderFromButton:(id)sender; |
+- (void)validateMenuSpacing; |
+@end |
+ |
+@implementation BookmarkBarFolderController(MakeTestingEasier) |
+- (IBAction)openBookmarkFolderFromButton:(id)sender { |
+ [[self folderTarget] openBookmarkFolderFromButton:sender]; |
+} |
+ |
+// Utility function to verify that the buttons in this folder are all |
+// evenly spaced in a progressive manner. |
+- (void)validateMenuSpacing { |
+ BOOL firstButton = YES; |
+ CGFloat lastVerticalOffset = 0.0; |
+ for (BookmarkButton* button in [self buttons]) { |
+ if (firstButton) { |
+ firstButton = NO; |
+ lastVerticalOffset = [button frame].origin.y; |
+ } else { |
+ CGFloat nextVerticalOffset = [button frame].origin.y; |
+ EXPECT_CGFLOAT_EQ(lastVerticalOffset - |
+ bookmarks::kBookmarkFolderButtonHeight, |
+ nextVerticalOffset); |
+ lastVerticalOffset = nextVerticalOffset; |
+ } |
+ } |
+} |
+@end |
+ |
+// Don't use a high window level when running unit tests -- it'll |
+// interfere with anything else you are working on. |
+// For testing. |
+@interface BookmarkBarFolderControllerNoLevel : BookmarkBarFolderController |
+@end |
+ |
+@implementation BookmarkBarFolderControllerNoLevel |
+- (void)configureWindowLevel { |
+ // Intentionally empty. |
+} |
+@end |
+ |
+@interface BookmarkBarFolderControllerPong : BookmarkBarFolderController { |
+ BOOL childFolderWillShow_; |
+ BOOL childFolderWillClose_; |
+} |
+@property (nonatomic, readonly) BOOL childFolderWillShow; |
+@property (nonatomic, readonly) BOOL childFolderWillClose; |
+@end |
+ |
+@implementation BookmarkBarFolderControllerPong |
+@synthesize childFolderWillShow = childFolderWillShow_; |
+@synthesize childFolderWillClose = childFolderWillClose_; |
+ |
+- (void)childFolderWillShow:(id<BookmarkButtonControllerProtocol>)child { |
+ childFolderWillShow_ = YES; |
+} |
+ |
+- (void)childFolderWillClose:(id<BookmarkButtonControllerProtocol>)child { |
+ childFolderWillClose_ = YES; |
+} |
+ |
+// We don't have a real BookmarkBarController as our parent root so |
+// we fake this one out. |
+- (void)closeAllBookmarkFolders { |
+ [self closeBookmarkFolder:self]; |
+} |
+ |
+@end |
+ |
namespace { |
const int kLotsOfNodesCount = 150; |
}; |
+// Redirect certain calls so they can be seen by tests. |
+ |
+@interface BookmarkBarControllerChildFolderRedirect : BookmarkBarController { |
+ BookmarkBarFolderController* childFolderDelegate_; |
+} |
+@property (nonatomic, assign) BookmarkBarFolderController* childFolderDelegate; |
+@end |
+ |
+@implementation BookmarkBarControllerChildFolderRedirect |
+ |
+@synthesize childFolderDelegate = childFolderDelegate_; |
+ |
+- (void)childFolderWillShow:(id<BookmarkButtonControllerProtocol>)child { |
+ [childFolderDelegate_ childFolderWillShow:child]; |
+} |
+ |
+- (void)childFolderWillClose:(id<BookmarkButtonControllerProtocol>)child { |
+ [childFolderDelegate_ childFolderWillClose:child]; |
+} |
+ |
+@end |
+ |
+ |
class BookmarkBarFolderControllerTest : public CocoaProfileTest { |
public: |
- BookmarkModel* GetModel() { |
- return profile()->GetBookmarkModel(); |
+ scoped_nsobject<BookmarkBarControllerChildFolderRedirect> bar_; |
+ const BookmarkNode* folderA_; // Owned by model. |
+ const BookmarkNode* longTitleNode_; // Owned by model. |
+ |
+ virtual void SetUp() { |
+ CocoaProfileTest::SetUp(); |
+ ASSERT_TRUE(profile()); |
+ |
+ CreateModel(); |
+ } |
+ |
+ void CreateModel() { |
+ BookmarkModel* model = profile()->GetBookmarkModel(); |
+ const BookmarkNode* parent = model->bookmark_bar_node(); |
+ const BookmarkNode* folderA = model->AddFolder(parent, |
+ parent->child_count(), |
+ ASCIIToUTF16("folder")); |
+ folderA_ = folderA; |
+ model->AddFolder(parent, parent->child_count(), |
+ ASCIIToUTF16("sibbling folder")); |
+ const BookmarkNode* folderB = model->AddFolder(folderA, |
+ folderA->child_count(), |
+ ASCIIToUTF16("subfolder 1")); |
+ model->AddFolder(folderA, |
+ folderA->child_count(), |
+ ASCIIToUTF16("subfolder 2")); |
+ model->AddURL(folderA, folderA->child_count(), ASCIIToUTF16("title a"), |
+ GURL("http://www.google.com/a")); |
+ longTitleNode_ = model->AddURL( |
+ folderA, folderA->child_count(), |
+ ASCIIToUTF16("title super duper long long whoa momma title you betcha"), |
+ GURL("http://www.google.com/b")); |
+ model->AddURL(folderB, folderB->child_count(), ASCIIToUTF16("t"), |
+ GURL("http://www.google.com/c")); |
+ |
+ bar_.reset( |
+ [[BookmarkBarControllerChildFolderRedirect alloc] |
+ initWithBrowser:browser() |
+ initialWidth:300 |
+ delegate:nil |
+ resizeDelegate:nil]); |
+ [bar_ loaded:model]; |
+ // Make parent frame for bookmark bar then open it. |
+ NSRect frame = [[test_window() contentView] frame]; |
+ frame = NSMakeRect(frame.origin.x, |
+ frame.size.height - bookmarks::kNTPBookmarkBarHeight, |
+ frame.size.width, bookmarks::kNTPBookmarkBarHeight); |
+ NSView* fakeToolbarView = [[[NSView alloc] initWithFrame:frame] |
+ autorelease]; |
+ [[test_window() contentView] addSubview:fakeToolbarView]; |
+ [fakeToolbarView addSubview:[bar_ view]]; |
+ [bar_ setBookmarkBarEnabled:YES]; |
} |
- BookmarkBarFolderController* CreateController(const BookmarkNode* node) { |
- // The button will be owned by the controller. |
- scoped_nsobject<BookmarkButton> button( |
- [[BookmarkButton alloc] initWithFrame:NSMakeRect(0, 0, 500, 500)]); |
- scoped_nsobject<BookmarkButtonCell> cell( |
- [[BookmarkButtonCell alloc] initTextCell:@"foo"]); |
- [button setCell:cell]; |
- [cell setBookmarkNode:node]; |
+ // Remove the bookmark with the long title. |
+ void RemoveLongTitleNode() { |
+ BookmarkModel* model = profile()->GetBookmarkModel(); |
+ model->Remove(longTitleNode_->parent(), |
+ longTitleNode_->parent()->GetIndexOf(longTitleNode_)); |
+ } |
- BookmarkModel* model = GetModel(); |
- return [[BookmarkBarFolderController alloc] initWithParentButton:button |
- bookmarkModel:model |
- barController:nil]; |
+ // Add LOTS of nodes to our model if needed (e.g. scrolling). |
+ // Returns the number of nodes added. |
+ int AddLotsOfNodes() { |
+ BookmarkModel* model = profile()->GetBookmarkModel(); |
+ for (int i = 0; i < kLotsOfNodesCount; i++) { |
+ model->AddURL(folderA_, folderA_->child_count(), |
+ ASCIIToUTF16("repeated title"), |
+ GURL("http://www.google.com/repeated/url")); |
+ } |
+ return kLotsOfNodesCount; |
} |
- NSMenu* GetMenu(BookmarkBarFolderController* controller) { |
- return [[controller menuBridge]->controller() menu]; |
+ // Return a simple BookmarkBarFolderController. |
+ BookmarkBarFolderControllerPong* SimpleBookmarkBarFolderController() { |
+ BookmarkButton* parentButton = [[bar_ buttons] objectAtIndex:0]; |
+ BookmarkBarFolderControllerPong* c = |
+ [[BookmarkBarFolderControllerPong alloc] |
+ initWithParentButton:parentButton |
+ parentController:nil |
+ barController:bar_]; |
+ [c window]; // Force nib load. |
+ return c; |
} |
}; |
-TEST_F(BookmarkBarFolderControllerTest, SimpleFolder) { |
- // Create the model. |
- BookmarkModel* model = GetModel(); |
- const BookmarkNode* root = model->bookmark_bar_node(); |
- |
- model->AddURL(root, root->child_count(), ASCIIToUTF16("ignored"), |
- GURL("http://example.com")); |
- |
- const BookmarkNode* folder = model->AddFolder(root, root->child_count(), |
- ASCIIToUTF16("folder")); |
- model->AddURL(folder, folder->child_count(), ASCIIToUTF16("item 1"), |
- GURL("http://www.google.com/")); |
- model->AddURL(folder, folder->child_count(), ASCIIToUTF16("item 2"), |
- GURL("http://www.chromium.org/")); |
- model->AddURL(folder, folder->child_count(), ASCIIToUTF16("item 3"), |
- GURL("http://build.chromium.org/")); |
- |
- model->AddURL(root, root->child_count(), ASCIIToUTF16("ignored 2"), |
- GURL("http://example2.com")); |
- |
- // Create the controller and menu. |
- scoped_nsobject<BookmarkBarFolderController> bbfc(CreateController(folder)); |
- CloseFolderAfterDelay(bbfc, 0.1); |
- [bbfc openMenu]; |
- |
- NSArray* items = [GetMenu(bbfc) itemArray]; |
- ASSERT_EQ(3u, [items count]); |
- |
- EXPECT_NSEQ(@"item 1", [[items objectAtIndex:0] title]); |
- EXPECT_NSEQ(@"item 2", [[items objectAtIndex:1] title]); |
- EXPECT_NSEQ(@"item 3", [[items objectAtIndex:2] title]); |
-} |
- |
-TEST_F(BookmarkBarFolderControllerTest, NestedFolder) { |
- // Create the model. |
- BookmarkModel* model = GetModel(); |
- const BookmarkNode* root = model->bookmark_bar_node(); |
- |
- model->AddURL(root, root->child_count(), ASCIIToUTF16("ignored"), |
- GURL("http://example.com")); |
- model->AddURL(root, root->child_count(), ASCIIToUTF16("ignored 2"), |
- GURL("http://example2.com")); |
- |
- const BookmarkNode* folder = model->AddFolder(root, root->child_count(), |
- ASCIIToUTF16("folder")); |
- model->AddURL(folder, folder->child_count(), ASCIIToUTF16("item 1"), |
- GURL("http://www.google.com/")); |
- model->AddURL(folder, folder->child_count(), ASCIIToUTF16("item 2"), |
- GURL("http://www.chromium.org/")); |
- model->AddURL(folder, folder->child_count(), ASCIIToUTF16("item 3"), |
- GURL("http://build.chromium.org/")); |
- const BookmarkNode* subfolder = model->AddFolder(folder, |
- folder->child_count(), ASCIIToUTF16("subfolder")); |
- model->AddURL(folder, folder->child_count(), ASCIIToUTF16("item 4"), |
- GURL("http://dev.chromium.org/")); |
- |
- model->AddURL(subfolder, subfolder->child_count(), ASCIIToUTF16("subitem 1"), |
- GURL("http://gmail.com")); |
- model->AddURL(subfolder, subfolder->child_count(), ASCIIToUTF16("subitem 2"), |
- GURL("http://google.com/+")); |
- |
- // Create the controller and menu. |
- scoped_nsobject<BookmarkBarFolderController> bbfc(CreateController(folder)); |
- CloseFolderAfterDelay(bbfc, 0.1); |
- [bbfc openMenu]; |
- |
- NSArray* items = [GetMenu(bbfc) itemArray]; |
- ASSERT_EQ(5u, [items count]); |
- |
- EXPECT_NSEQ(@"item 1", [[items objectAtIndex:0] title]); |
- EXPECT_NSEQ(@"item 2", [[items objectAtIndex:1] title]); |
- EXPECT_NSEQ(@"item 3", [[items objectAtIndex:2] title]); |
- EXPECT_NSEQ(@"subfolder", [[items objectAtIndex:3] title]); |
- EXPECT_NSEQ(@"item 4", [[items objectAtIndex:4] title]); |
- |
- NSArray* subitems = [[[items objectAtIndex:3] submenu] itemArray]; |
- ASSERT_EQ(2u, [subitems count]); |
- EXPECT_NSEQ(@"subitem 1", [[subitems objectAtIndex:0] title]); |
- EXPECT_NSEQ(@"subitem 2", [[subitems objectAtIndex:1] title]); |
-} |
- |
-TEST_F(BookmarkBarFolderControllerTest, OffTheSide) { |
- // Create the model. |
- BookmarkModel* model = GetModel(); |
- const BookmarkNode* root = model->bookmark_bar_node(); |
- |
- model->AddURL(root, root->child_count(), ASCIIToUTF16("item 1"), |
- GURL("http://example.com")); |
- model->AddURL(root, root->child_count(), ASCIIToUTF16("item 2"), |
- GURL("http://www.google.com/")); |
- model->AddURL(root, root->child_count(), ASCIIToUTF16("item 3"), |
- GURL("http://www.chromium.org/")); |
- model->AddURL(root, root->child_count(), ASCIIToUTF16("item 4"), |
- GURL("http://build.chromium.org/")); |
- model->AddURL(root, root->child_count(), ASCIIToUTF16("item 5"), |
- GURL("http://example2.com")); |
- |
- // Create the controller and menu. |
- scoped_nsobject<BookmarkBarFolderController> bbfc(CreateController(root)); |
- CloseFolderAfterDelay(bbfc, 0.1); |
- [bbfc openMenu]; |
- |
- NSArray* items = [GetMenu(bbfc) itemArray]; |
- ASSERT_EQ(5u, [items count]); |
- |
- EXPECT_NSEQ(@"item 1", [[items objectAtIndex:0] title]); |
- EXPECT_NSEQ(@"item 2", [[items objectAtIndex:1] title]); |
- EXPECT_NSEQ(@"item 3", [[items objectAtIndex:2] title]); |
- EXPECT_NSEQ(@"item 4", [[items objectAtIndex:3] title]); |
- EXPECT_NSEQ(@"item 5", [[items objectAtIndex:4] title]); |
- |
- [bbfc setOffTheSideNodeStartIndex:1]; |
- CloseFolderAfterDelay(bbfc, 0.1); |
- [bbfc openMenu]; |
- items = [GetMenu(bbfc) itemArray]; |
- ASSERT_EQ(4u, [items count]); |
- EXPECT_NSEQ(@"item 2", [[items objectAtIndex:0] title]); |
- |
- [bbfc setOffTheSideNodeStartIndex:4]; |
- CloseFolderAfterDelay(bbfc, 0.1); |
- [bbfc openMenu]; |
- items = [GetMenu(bbfc) itemArray]; |
- ASSERT_EQ(1u, [items count]); |
- EXPECT_NSEQ(@"item 5", [[items objectAtIndex:0] title]); |
- |
- [bbfc setOffTheSideNodeStartIndex:0]; |
- CloseFolderAfterDelay(bbfc, 0.1); |
- [bbfc openMenu]; |
- items = [GetMenu(bbfc) itemArray]; |
- EXPECT_EQ(5u, [items count]); |
+TEST_F(BookmarkBarFolderControllerTest, InitCreateAndDelete) { |
+ scoped_nsobject<BookmarkBarFolderController> bbfc; |
+ bbfc.reset(SimpleBookmarkBarFolderController()); |
+ |
+ // Make sure none of the buttons overlap, that all are inside |
+ // the content frame, and their cells are of the proper class. |
+ NSArray* buttons = [bbfc buttons]; |
+ EXPECT_TRUE([buttons count]); |
+ for (unsigned int i = 0; i < ([buttons count]-1); i++) { |
+ EXPECT_FALSE(NSContainsRect([[buttons objectAtIndex:i] frame], |
+ [[buttons objectAtIndex:i+1] frame])); |
+ } |
+ Class cellClass = [BookmarkBarFolderButtonCell class]; |
+ for (BookmarkButton* button in buttons) { |
+ NSRect r = [[bbfc folderView] convertRect:[button frame] fromView:button]; |
+ // TODO(jrg): remove this adjustment. |
+ NSRect bigger = NSInsetRect([[bbfc folderView] frame], -2, 0); |
+ EXPECT_TRUE(NSContainsRect(bigger, r)); |
+ EXPECT_TRUE([[button cell] isKindOfClass:cellClass]); |
+ } |
+ |
+ // Confirm folder buttons have no tooltip. The important thing |
+ // really is that we insure folders and non-folders are treated |
+ // differently; not sure of any other generic way to do this. |
+ for (BookmarkButton* button in buttons) { |
+ if ([button isFolder]) |
+ EXPECT_FALSE([button toolTip]); |
+ else |
+ EXPECT_TRUE([button toolTip]); |
+ } |
+} |
+ |
+// Make sure closing of the window releases the controller. |
+// (e.g. valgrind shouldn't complain if we do this). |
+TEST_F(BookmarkBarFolderControllerTest, ReleaseOnClose) { |
+ scoped_nsobject<BookmarkBarFolderController> bbfc; |
+ bbfc.reset(SimpleBookmarkBarFolderController()); |
+ EXPECT_TRUE(bbfc.get()); |
+ |
+ [bbfc retain]; // stop the scoped_nsobject from doing anything |
+ [[bbfc window] close]; // trigger an autorelease of bbfc.get() |
+} |
+ |
+TEST_F(BookmarkBarFolderControllerTest, BasicPosition) { |
+ BookmarkButton* parentButton = [[bar_ buttons] objectAtIndex:0]; |
+ EXPECT_TRUE(parentButton); |
+ |
+ // If parent is a BookmarkBarController, grow down. |
+ scoped_nsobject<BookmarkBarFolderController> bbfc; |
+ bbfc.reset([[BookmarkBarFolderController alloc] |
+ initWithParentButton:parentButton |
+ parentController:nil |
+ barController:bar_]); |
+ [bbfc window]; |
+ NSPoint pt = [bbfc windowTopLeftForWidth:0 height:100]; // screen coords |
+ NSPoint buttonOriginInScreen = |
+ [[parentButton window] |
+ convertBaseToScreen:[parentButton |
+ convertRectToBase:[parentButton frame]].origin]; |
+ // Within margin |
+ EXPECT_LE(abs(pt.x - buttonOriginInScreen.x), |
+ bookmarks::kBookmarkMenuOverlap+1); |
+ EXPECT_LE(abs(pt.y - buttonOriginInScreen.y), |
+ bookmarks::kBookmarkMenuOverlap+1); |
+ |
+ // Make sure we see the window shift left if it spills off the screen |
+ pt = [bbfc windowTopLeftForWidth:0 height:100]; |
+ NSPoint shifted = [bbfc windowTopLeftForWidth:9999999 height:100]; |
+ EXPECT_LT(shifted.x, pt.x); |
+ |
+ // If parent is a BookmarkBarFolderController, grow right. |
+ scoped_nsobject<BookmarkBarFolderController> bbfc2; |
+ bbfc2.reset([[BookmarkBarFolderController alloc] |
+ initWithParentButton:[[bbfc buttons] objectAtIndex:0] |
+ parentController:bbfc.get() |
+ barController:bar_]); |
+ [bbfc2 window]; |
+ pt = [bbfc2 windowTopLeftForWidth:0 height:100]; |
+ // We're now overlapping the window a bit. |
+ EXPECT_EQ(pt.x, NSMaxX([[bbfc.get() window] frame]) - |
+ bookmarks::kBookmarkMenuOverlap); |
+} |
+ |
+// Confirm we grow right until end of screen, then start growing left |
+// until end of screen again, then right. |
+TEST_F(BookmarkBarFolderControllerTest, PositionRightLeftRight) { |
+ BookmarkModel* model = profile()->GetBookmarkModel(); |
+ const BookmarkNode* parent = model->bookmark_bar_node(); |
+ const BookmarkNode* folder = parent; |
+ |
+ const int count = 100; |
+ int i; |
+ // Make some super duper deeply nested folders. |
+ for (i = 0; i < count; i++) { |
+ folder = model->AddFolder(folder, 0, ASCIIToUTF16("nested folder")); |
+ } |
+ |
+ // Setup initial state for opening all folders. |
+ folder = parent; |
+ BookmarkButton* parentButton = [[bar_ buttons] objectAtIndex:0]; |
+ BookmarkBarFolderController* parentController = nil; |
+ EXPECT_TRUE(parentButton); |
+ |
+ // Open them all. |
+ scoped_nsobject<NSMutableArray> folder_controller_array; |
+ folder_controller_array.reset([[NSMutableArray array] retain]); |
+ for (i=0; i<count; i++) { |
+ BookmarkBarFolderControllerNoLevel* bbfcl = |
+ [[BookmarkBarFolderControllerNoLevel alloc] |
+ initWithParentButton:parentButton |
+ parentController:parentController |
+ barController:bar_]; |
+ [folder_controller_array addObject:bbfcl]; |
+ [bbfcl autorelease]; |
+ [bbfcl window]; |
+ parentController = bbfcl; |
+ parentButton = [[bbfcl buttons] objectAtIndex:0]; |
+ } |
+ |
+ // Make vector of all x positions. |
+ std::vector<CGFloat> leftPositions; |
+ for (i=0; i<count; i++) { |
+ CGFloat x = [[[folder_controller_array objectAtIndex:i] window] |
+ frame].origin.x; |
+ leftPositions.push_back(x); |
+ } |
+ |
+ // Make sure the first few grow right. |
+ for (i=0; i<3; i++) |
+ EXPECT_TRUE(leftPositions[i+1] > leftPositions[i]); |
+ |
+ // Look for the first "grow left". |
+ while (leftPositions[i] > leftPositions[i-1]) |
+ i++; |
+ // Confirm the next few also grow left. |
+ int j; |
+ for (j=i; j<i+3; j++) |
+ EXPECT_TRUE(leftPositions[j+1] < leftPositions[j]); |
+ i = j; |
+ |
+ // Finally, confirm we see a "grow right" once more. |
+ while (leftPositions[i] < leftPositions[i-1]) |
+ i++; |
+ // (No need to EXPECT a final "grow right"; if we didn't find one |
+ // we'd get a C++ array bounds exception). |
+} |
+ |
+TEST_F(BookmarkBarFolderControllerTest, DropDestination) { |
+ scoped_nsobject<BookmarkBarFolderController> bbfc; |
+ bbfc.reset(SimpleBookmarkBarFolderController()); |
+ EXPECT_TRUE(bbfc.get()); |
+ |
+ // Confirm "off the top" and "off the bottom" match no buttons. |
+ NSPoint p = NSMakePoint(NSMidX([[bbfc folderView] frame]), 10000); |
+ EXPECT_FALSE([bbfc buttonForDroppingOnAtPoint:p]); |
+ EXPECT_TRUE([bbfc shouldShowIndicatorShownForPoint:p]); |
+ p = NSMakePoint(NSMidX([[bbfc folderView] frame]), -1); |
+ EXPECT_FALSE([bbfc buttonForDroppingOnAtPoint:p]); |
+ EXPECT_TRUE([bbfc shouldShowIndicatorShownForPoint:p]); |
+ |
+ // Confirm "right in the center" (give or take a pixel) is a match, |
+ // and confirm "just barely in the button" is not. Anything more |
+ // specific seems likely to be tweaked. We don't loop over all |
+ // buttons because the scroll view makes them not visible. |
+ for (BookmarkButton* button in [bbfc buttons]) { |
+ CGFloat x = NSMidX([button frame]); |
+ CGFloat y = NSMidY([button frame]); |
+ // Somewhere near the center: a match (but only if a folder!) |
+ if ([button isFolder]) { |
+ EXPECT_EQ(button, |
+ [bbfc buttonForDroppingOnAtPoint:NSMakePoint(x-1, y+1)]); |
+ EXPECT_EQ(button, |
+ [bbfc buttonForDroppingOnAtPoint:NSMakePoint(x+1, y-1)]); |
+ EXPECT_FALSE([bbfc shouldShowIndicatorShownForPoint:NSMakePoint(x, y)]);; |
+ } else { |
+ // If not a folder we don't drop into it. |
+ EXPECT_FALSE([bbfc buttonForDroppingOnAtPoint:NSMakePoint(x-1, y+1)]); |
+ EXPECT_FALSE([bbfc buttonForDroppingOnAtPoint:NSMakePoint(x+1, y-1)]); |
+ EXPECT_TRUE([bbfc shouldShowIndicatorShownForPoint:NSMakePoint(x, y)]);; |
+ } |
+ } |
} |
+ |
+TEST_F(BookmarkBarFolderControllerTest, OpenFolder) { |
+ scoped_nsobject<BookmarkBarFolderController> bbfc; |
+ bbfc.reset(SimpleBookmarkBarFolderController()); |
+ EXPECT_TRUE(bbfc.get()); |
+ |
+ EXPECT_FALSE([bbfc folderController]); |
+ BookmarkButton* button = [[bbfc buttons] objectAtIndex:0]; |
+ [bbfc openBookmarkFolderFromButton:button]; |
+ id controller = [bbfc folderController]; |
+ EXPECT_TRUE(controller); |
+ EXPECT_EQ([controller parentButton], button); |
+ |
+ // Click the same one --> it gets closed. |
+ [bbfc openBookmarkFolderFromButton:[[bbfc buttons] objectAtIndex:0]]; |
+ EXPECT_FALSE([bbfc folderController]); |
+ |
+ // Open a new one --> change. |
+ [bbfc openBookmarkFolderFromButton:[[bbfc buttons] objectAtIndex:1]]; |
+ EXPECT_NE(controller, [bbfc folderController]); |
+ EXPECT_NE([[bbfc folderController] parentButton], button); |
+ |
+ // Close it --> all gone! |
+ [bbfc closeBookmarkFolder:nil]; |
+ EXPECT_FALSE([bbfc folderController]); |
+} |
+ |
+TEST_F(BookmarkBarFolderControllerTest, ChildFolderCallbacks) { |
+ scoped_nsobject<BookmarkBarFolderControllerPong> bbfc; |
+ bbfc.reset(SimpleBookmarkBarFolderController()); |
+ EXPECT_TRUE(bbfc.get()); |
+ [bar_ setChildFolderDelegate:bbfc.get()]; |
+ |
+ EXPECT_FALSE([bbfc childFolderWillShow]); |
+ [bbfc openBookmarkFolderFromButton:[[bbfc buttons] objectAtIndex:0]]; |
+ EXPECT_TRUE([bbfc childFolderWillShow]); |
+ |
+ EXPECT_FALSE([bbfc childFolderWillClose]); |
+ [bbfc closeBookmarkFolder:nil]; |
+ EXPECT_TRUE([bbfc childFolderWillClose]); |
+ |
+ [bar_ setChildFolderDelegate:nil]; |
+} |
+ |
+// Make sure bookmark folders have variable widths. |
+TEST_F(BookmarkBarFolderControllerTest, ChildFolderWidth) { |
+ scoped_nsobject<BookmarkBarFolderController> bbfc; |
+ |
+ bbfc.reset(SimpleBookmarkBarFolderController()); |
+ EXPECT_TRUE(bbfc.get()); |
+ [bbfc showWindow:bbfc.get()]; |
+ CGFloat wideWidth = NSWidth([[bbfc window] frame]); |
+ |
+ RemoveLongTitleNode(); |
+ bbfc.reset(SimpleBookmarkBarFolderController()); |
+ EXPECT_TRUE(bbfc.get()); |
+ CGFloat thinWidth = NSWidth([[bbfc window] frame]); |
+ |
+ // Make sure window size changed as expected. |
+ EXPECT_GT(wideWidth, thinWidth); |
+} |
+ |
+// Simple scrolling tests. |
+// Currently flaky due to a changed definition of the correct menu boundaries. |
+TEST_F(BookmarkBarFolderControllerTest, DISABLED_SimpleScroll) { |
+ scoped_nsobject<BookmarkBarFolderController> bbfc; |
+ NSRect screenFrame = [[NSScreen mainScreen] visibleFrame]; |
+ CGFloat screenHeight = NSHeight(screenFrame); |
+ int nodecount = AddLotsOfNodes(); |
+ bbfc.reset(SimpleBookmarkBarFolderController()); |
+ EXPECT_TRUE(bbfc.get()); |
+ [bbfc showWindow:bbfc.get()]; |
+ NSWindow* window = [bbfc window]; |
+ |
+ // The window should be shorter than the screen but reach exactly to the |
+ // bottom of the screen since it's scrollable. |
+ EXPECT_LT(NSHeight([window frame]), screenHeight); |
+ EXPECT_CGFLOAT_EQ(0.0, [window frame].origin.y); |
+ |
+ // Initially, should show scroll-up but not scroll-down. |
+ EXPECT_TRUE([bbfc canScrollUp]); |
+ EXPECT_FALSE([bbfc canScrollDown]); |
+ |
+ // Scroll up a bit. Make sure the window has gotten bigger each time. |
+ // Also, for each scroll, make sure our hit test finds a new button |
+ // (to confirm the content area changed). |
+ NSView* savedHit = nil; |
+ NSScrollView* scrollView = [bbfc scrollView]; |
+ |
+ // Find the next-to-last button showing at the bottom of the window and |
+ // use its center for hit testing. |
+ BookmarkButton* targetButton = nil; |
+ NSPoint scrollPoint = [scrollView documentVisibleRect].origin; |
+ for (BookmarkButton* button in [bbfc buttons]) { |
+ NSRect buttonFrame = [button frame]; |
+ buttonFrame.origin.y -= scrollPoint.y; |
+ if (buttonFrame.origin.y < 0.0) |
+ break; |
+ targetButton = button; |
+ } |
+ EXPECT_TRUE(targetButton != nil); |
+ NSPoint hitPoint = [targetButton frame].origin; |
+ hitPoint.x += 50.0; |
+ hitPoint.y += (bookmarks::kBookmarkFolderButtonHeight / 2.0) - scrollPoint.y; |
+ hitPoint = [targetButton convertPoint:hitPoint toView:scrollView]; |
+ |
+ for (int i = 0; i < 3; i++) { |
+ CGFloat height = NSHeight([window frame]); |
+ [bbfc performOneScroll:60]; |
+ EXPECT_GT(NSHeight([window frame]), height); |
+ NSView* hit = [scrollView hitTest:hitPoint]; |
+ // We should hit a bookmark button. |
+ EXPECT_TRUE([[hit className] isEqualToString:@"BookmarkButton"]); |
+ EXPECT_NE(hit, savedHit); |
+ savedHit = hit; |
+ } |
+ |
+ // Keep scrolling up; make sure we never get bigger than the screen. |
+ // Also confirm we never scroll the window off the screen. |
+ bool bothAtOnce = false; |
+ while ([bbfc canScrollUp]) { |
+ [bbfc performOneScroll:60]; |
+ EXPECT_TRUE(NSContainsRect([[NSScreen mainScreen] frame], [window frame])); |
+ // Make sure, sometime during our scroll, we have the ability to |
+ // scroll in either direction. |
+ if ([bbfc canScrollUp] && |
+ [bbfc canScrollDown]) |
+ bothAtOnce = true; |
+ } |
+ EXPECT_TRUE(bothAtOnce); |
+ |
+ // Once we've scrolled to the end, our only option should be to scroll back. |
+ EXPECT_FALSE([bbfc canScrollUp]); |
+ EXPECT_TRUE([bbfc canScrollDown]); |
+ |
+ NSRect wholeScreenRect = [[NSScreen mainScreen] frame]; |
+ |
+ // Now scroll down and make sure the window size does not change. |
+ // Also confirm we never scroll the window off the screen the other |
+ // way. |
+ for (int i = 0; i < nodecount+50; ++i) { |
+ [bbfc performOneScroll:-60]; |
+ // Once we can no longer scroll down the window height changes. |
+ if (![bbfc canScrollDown]) |
+ break; |
+ EXPECT_TRUE(NSContainsRect(wholeScreenRect, [window frame])); |
+ } |
+ |
+ EXPECT_GT(NSHeight(wholeScreenRect), NSHeight([window frame])); |
+ EXPECT_TRUE(NSContainsRect(wholeScreenRect, [window frame])); |
+} |
+ |
+// Folder menu sizing and placement while deleting bookmarks |
+// and scrolling tests. |
+TEST_F(BookmarkBarFolderControllerTest, MenuPlacementWhileScrollingDeleting) { |
+ scoped_nsobject<BookmarkBarFolderController> bbfc; |
+ AddLotsOfNodes(); |
+ bbfc.reset(SimpleBookmarkBarFolderController()); |
+ [bbfc showWindow:bbfc.get()]; |
+ NSWindow* menuWindow = [bbfc window]; |
+ BookmarkBarFolderController* folder = [bar_ folderController]; |
+ NSArray* buttons = [folder buttons]; |
+ |
+ // Before scrolling any, delete a bookmark and make sure the window top has |
+ // not moved. Pick a button which is near the top and visible. |
+ CGFloat oldTop = [menuWindow frame].origin.y + NSHeight([menuWindow frame]); |
+ BookmarkButton* button = [buttons objectAtIndex:3]; |
+ [folder deleteBookmark:button]; |
+ CGFloat newTop = [menuWindow frame].origin.y + NSHeight([menuWindow frame]); |
+ EXPECT_CGFLOAT_EQ(oldTop, newTop); |
+ |
+ // Scroll so that both the top and bottom scroll arrows show, make sure |
+ // the top of the window has moved up, then delete a visible button and |
+ // make sure the top has not moved. |
+ oldTop = newTop; |
+ const CGFloat scrollOneBookmark = bookmarks::kBookmarkFolderButtonHeight + |
+ bookmarks::kBookmarkVerticalPadding; |
+ NSUInteger buttonCounter = 0; |
+ NSUInteger extraButtonLimit = 3; |
+ while (![bbfc canScrollDown] || extraButtonLimit > 0) { |
+ [bbfc performOneScroll:scrollOneBookmark]; |
+ ++buttonCounter; |
+ if ([bbfc canScrollDown]) |
+ --extraButtonLimit; |
+ } |
+ newTop = [menuWindow frame].origin.y + NSHeight([menuWindow frame]); |
+ EXPECT_NE(oldTop, newTop); |
+ oldTop = newTop; |
+ button = [buttons objectAtIndex:buttonCounter + 3]; |
+ [folder deleteBookmark:button]; |
+ newTop = [menuWindow frame].origin.y + NSHeight([menuWindow frame]); |
+ EXPECT_CGFLOAT_EQ(oldTop, newTop); |
+ |
+ // Scroll so that the top scroll arrow is no longer showing, make sure |
+ // the top of the window has not moved, then delete a visible button and |
+ // make sure the top has not moved. |
+ while ([bbfc canScrollDown]) { |
+ [bbfc performOneScroll:-scrollOneBookmark]; |
+ --buttonCounter; |
+ } |
+ button = [buttons objectAtIndex:buttonCounter + 3]; |
+ [folder deleteBookmark:button]; |
+ newTop = [menuWindow frame].origin.y + NSHeight([menuWindow frame]); |
+ EXPECT_CGFLOAT_EQ(oldTop - bookmarks::kScrollWindowVerticalMargin, newTop); |
+} |
+ |
+@interface FakedDragInfo : NSObject { |
+@public |
+ NSPoint dropLocation_; |
+ NSDragOperation sourceMask_; |
+} |
+@property (nonatomic, assign) NSPoint dropLocation; |
+- (void)setDraggingSourceOperationMask:(NSDragOperation)mask; |
+@end |
+ |
+@implementation FakedDragInfo |
+ |
+@synthesize dropLocation = dropLocation_; |
+ |
+- (id)init { |
+ if ((self = [super init])) { |
+ dropLocation_ = NSZeroPoint; |
+ sourceMask_ = NSDragOperationMove; |
+ } |
+ return self; |
+} |
+ |
+// NSDraggingInfo protocol functions. |
+ |
+- (id)draggingPasteboard { |
+ return self; |
+} |
+ |
+- (id)draggingSource { |
+ return self; |
+} |
+ |
+- (NSDragOperation)draggingSourceOperationMask { |
+ return sourceMask_; |
+} |
+ |
+- (NSPoint)draggingLocation { |
+ return dropLocation_; |
+} |
+ |
+// Other functions. |
+ |
+- (void)setDraggingSourceOperationMask:(NSDragOperation)mask { |
+ sourceMask_ = mask; |
+} |
+ |
+@end |
+ |
+ |
+class BookmarkBarFolderControllerMenuTest : public CocoaProfileTest { |
+ public: |
+ scoped_nsobject<NSView> parent_view_; |
+ scoped_nsobject<ViewResizerPong> resizeDelegate_; |
+ scoped_nsobject<BookmarkBarController> bar_; |
+ |
+ virtual void SetUp() { |
+ CocoaProfileTest::SetUp(); |
+ ASSERT_TRUE(browser()); |
+ |
+ resizeDelegate_.reset([[ViewResizerPong alloc] init]); |
+ NSRect parent_frame = NSMakeRect(0, 0, 800, 50); |
+ parent_view_.reset([[NSView alloc] initWithFrame:parent_frame]); |
+ [parent_view_ setHidden:YES]; |
+ bar_.reset([[BookmarkBarController alloc] |
+ initWithBrowser:browser() |
+ initialWidth:NSWidth(parent_frame) |
+ delegate:nil |
+ resizeDelegate:resizeDelegate_.get()]); |
+ InstallAndToggleBar(bar_.get()); |
+ } |
+ |
+ void InstallAndToggleBar(BookmarkBarController* bar) { |
+ // Force loading of the nib. |
+ [bar view]; |
+ // Awkwardness to look like we've been installed. |
+ [parent_view_ addSubview:[bar view]]; |
+ NSRect frame = [[[bar view] superview] frame]; |
+ frame.origin.y = 400; |
+ [[[bar view] superview] setFrame:frame]; |
+ |
+ // Make sure it's on in a window so viewDidMoveToWindow is called |
+ [[test_window() contentView] addSubview:parent_view_]; |
+ |
+ // Make sure it's open so certain things aren't no-ops. |
+ [bar updateAndShowNormalBar:YES |
+ showDetachedBar:NO |
+ withAnimation:NO]; |
+ } |
+}; |
+ |
+TEST_F(BookmarkBarFolderControllerMenuTest, DragMoveBarBookmarkToFolder) { |
+ WithNoAnimation at_all; |
+ BookmarkModel& model(*profile()->GetBookmarkModel()); |
+ const BookmarkNode* root = model.bookmark_bar_node(); |
+ const std::string model_string("1b 2f:[ 2f1b 2f2f:[ 2f2f1b 2f2f2b " |
+ "2f2f3b ] 2f3b ] 3b 4f:[ 4f1f:[ 4f1f1b 4f1f2b 4f1f3b ] 4f2f:[ 4f2f1b " |
+ "4f2f2b 4f2f3b ] 4f3f:[ 4f3f1b 4f3f2b 4f3f3b ] ] 5b "); |
+ model_test_utils::AddNodesFromModelString(model, root, model_string); |
+ |
+ // Validate initial model. |
+ std::string actualModelString = model_test_utils::ModelStringFromNode(root); |
+ EXPECT_EQ(model_string, actualModelString); |
+ |
+ // Pop up a folder menu and drag in a button from the bar. |
+ BookmarkButton* toFolder = [bar_ buttonWithTitleEqualTo:@"2f"]; |
+ NSRect oldToFolderFrame = [toFolder frame]; |
+ [[toFolder target] performSelector:@selector(openBookmarkFolderFromButton:) |
+ withObject:toFolder]; |
+ BookmarkBarFolderController* folderController = [bar_ folderController]; |
+ EXPECT_TRUE(folderController); |
+ NSWindow* toWindow = [folderController window]; |
+ EXPECT_TRUE(toWindow); |
+ NSRect oldToWindowFrame = [toWindow frame]; |
+ // Drag a bar button onto a bookmark (i.e. not a folder) in a folder |
+ // so it should end up below the target bookmark. |
+ BookmarkButton* draggedButton = [bar_ buttonWithTitleEqualTo:@"1b"]; |
+ ASSERT_TRUE(draggedButton); |
+ CGFloat horizontalShift = |
+ NSWidth([draggedButton frame]) + bookmarks::kBookmarkHorizontalPadding; |
+ BookmarkButton* targetButton = |
+ [folderController buttonWithTitleEqualTo:@"2f1b"]; |
+ ASSERT_TRUE(targetButton); |
+ [folderController dragButton:draggedButton |
+ to:[targetButton center] |
+ copy:NO]; |
+ // The button should have landed just after "2f1b". |
+ const std::string expected_string("2f:[ 2f1b 1b 2f2f:[ 2f2f1b " |
+ "2f2f2b 2f2f3b ] 2f3b ] 3b 4f:[ 4f1f:[ 4f1f1b 4f1f2b 4f1f3b ] 4f2f:[ " |
+ "4f2f1b 4f2f2b 4f2f3b ] 4f3f:[ 4f3f1b 4f3f2b 4f3f3b ] ] 5b "); |
+ EXPECT_EQ(expected_string, model_test_utils::ModelStringFromNode(root)); |
+ |
+ // Verify the window still appears by looking for its controller. |
+ EXPECT_TRUE([bar_ folderController]); |
+ |
+ // Gather the new frames. |
+ NSRect newToFolderFrame = [toFolder frame]; |
+ NSRect newToWindowFrame = [toWindow frame]; |
+ // The toFolder should have shifted left horizontally but not vertically. |
+ NSRect expectedToFolderFrame = |
+ NSOffsetRect(oldToFolderFrame, -horizontalShift, 0); |
+ EXPECT_NSRECT_EQ(expectedToFolderFrame, newToFolderFrame); |
+ // The toWindow should have shifted left horizontally, down vertically, |
+ // and grown vertically. |
+ NSRect expectedToWindowFrame = oldToWindowFrame; |
+ expectedToWindowFrame.origin.x -= horizontalShift; |
+ expectedToWindowFrame.origin.y -= bookmarks::kBookmarkFolderButtonHeight; |
+ expectedToWindowFrame.size.height += bookmarks::kBookmarkFolderButtonHeight; |
+ EXPECT_NSRECT_EQ(expectedToWindowFrame, newToWindowFrame); |
+ |
+ // Check button spacing. |
+ [folderController validateMenuSpacing]; |
+ |
+ // Move the button back to the bar at the beginning. |
+ draggedButton = [folderController buttonWithTitleEqualTo:@"1b"]; |
+ ASSERT_TRUE(draggedButton); |
+ targetButton = [bar_ buttonWithTitleEqualTo:@"2f"]; |
+ ASSERT_TRUE(targetButton); |
+ [bar_ dragButton:draggedButton |
+ to:[targetButton left] |
+ copy:NO]; |
+ EXPECT_EQ(model_string, model_test_utils::ModelStringFromNode(root)); |
+ // Don't check the folder window since it's not supposed to be showing. |
+} |
+ |
+TEST_F(BookmarkBarFolderControllerMenuTest, DragCopyBarBookmarkToFolder) { |
+ BookmarkModel& model(*profile()->GetBookmarkModel()); |
+ const BookmarkNode* root = model.bookmark_bar_node(); |
+ const std::string model_string("1b 2f:[ 2f1b 2f2f:[ 2f2f1b 2f2f2b " |
+ "2f2f3b ] 2f3b ] 3b 4f:[ 4f1f:[ 4f1f1b 4f1f2b 4f1f3b ] 4f2f:[ 4f2f1b " |
+ "4f2f2b 4f2f3b ] 4f3f:[ 4f3f1b 4f3f2b 4f3f3b ] ] 5b "); |
+ model_test_utils::AddNodesFromModelString(model, root, model_string); |
+ |
+ // Validate initial model. |
+ std::string actualModelString = model_test_utils::ModelStringFromNode(root); |
+ EXPECT_EQ(model_string, actualModelString); |
+ |
+ // Pop up a folder menu and copy in a button from the bar. |
+ BookmarkButton* toFolder = [bar_ buttonWithTitleEqualTo:@"2f"]; |
+ ASSERT_TRUE(toFolder); |
+ NSRect oldToFolderFrame = [toFolder frame]; |
+ [[toFolder target] performSelector:@selector(openBookmarkFolderFromButton:) |
+ withObject:toFolder]; |
+ BookmarkBarFolderController* folderController = [bar_ folderController]; |
+ EXPECT_TRUE(folderController); |
+ NSWindow* toWindow = [folderController window]; |
+ EXPECT_TRUE(toWindow); |
+ NSRect oldToWindowFrame = [toWindow frame]; |
+ // Drag a bar button onto a bookmark (i.e. not a folder) in a folder |
+ // so it should end up below the target bookmark. |
+ BookmarkButton* draggedButton = [bar_ buttonWithTitleEqualTo:@"1b"]; |
+ ASSERT_TRUE(draggedButton); |
+ BookmarkButton* targetButton = |
+ [folderController buttonWithTitleEqualTo:@"2f1b"]; |
+ ASSERT_TRUE(targetButton); |
+ [folderController dragButton:draggedButton |
+ to:[targetButton center] |
+ copy:YES]; |
+ // The button should have landed just after "2f1b". |
+ const std::string expected_1("1b 2f:[ 2f1b 1b 2f2f:[ 2f2f1b " |
+ "2f2f2b 2f2f3b ] 2f3b ] 3b 4f:[ 4f1f:[ 4f1f1b 4f1f2b 4f1f3b ] 4f2f:[ " |
+ "4f2f1b 4f2f2b 4f2f3b ] 4f3f:[ 4f3f1b 4f3f2b 4f3f3b ] ] 5b "); |
+ EXPECT_EQ(expected_1, model_test_utils::ModelStringFromNode(root)); |
+ |
+ // Gather the new frames. |
+ NSRect newToFolderFrame = [toFolder frame]; |
+ NSRect newToWindowFrame = [toWindow frame]; |
+ // The toFolder should have shifted. |
+ EXPECT_NSRECT_EQ(oldToFolderFrame, newToFolderFrame); |
+ // The toWindow should have shifted down vertically and grown vertically. |
+ NSRect expectedToWindowFrame = oldToWindowFrame; |
+ expectedToWindowFrame.origin.y -= bookmarks::kBookmarkFolderButtonHeight; |
+ expectedToWindowFrame.size.height += bookmarks::kBookmarkFolderButtonHeight; |
+ EXPECT_NSRECT_EQ(expectedToWindowFrame, newToWindowFrame); |
+ |
+ // Copy the button back to the bar after "3b". |
+ draggedButton = [folderController buttonWithTitleEqualTo:@"1b"]; |
+ ASSERT_TRUE(draggedButton); |
+ targetButton = [bar_ buttonWithTitleEqualTo:@"4f"]; |
+ ASSERT_TRUE(targetButton); |
+ [bar_ dragButton:draggedButton |
+ to:[targetButton left] |
+ copy:YES]; |
+ const std::string expected_2("1b 2f:[ 2f1b 1b 2f2f:[ 2f2f1b " |
+ "2f2f2b 2f2f3b ] 2f3b ] 3b 1b 4f:[ 4f1f:[ 4f1f1b 4f1f2b 4f1f3b ] 4f2f:[ " |
+ "4f2f1b 4f2f2b 4f2f3b ] 4f3f:[ 4f3f1b 4f3f2b 4f3f3b ] ] 5b "); |
+ EXPECT_EQ(expected_2, model_test_utils::ModelStringFromNode(root)); |
+} |
+ |
+TEST_F(BookmarkBarFolderControllerMenuTest, DragMoveBarBookmarkToSubfolder) { |
+ BookmarkModel& model(*profile()->GetBookmarkModel()); |
+ const BookmarkNode* root = model.bookmark_bar_node(); |
+ const std::string model_string("1b 2f:[ 2f1b 2f2f:[ 2f2f1b 2f2f2b " |
+ "2f2f3b ] 2f3b ] 3b 4f:[ 4f1f:[ 4f1f1b 4f1f2b 4f1f3b ] 4f2f:[ 4f2f1b " |
+ "4f2f2b 4f2f3b ] 4f3f:[ 4f3f1b 4f3f2b 4f3f3b ] ] 5b "); |
+ model_test_utils::AddNodesFromModelString(model, root, model_string); |
+ |
+ // Validate initial model. |
+ std::string actualModelString = model_test_utils::ModelStringFromNode(root); |
+ EXPECT_EQ(model_string, actualModelString); |
+ |
+ // Pop up a folder menu and a subfolder menu. |
+ BookmarkButton* toFolder = [bar_ buttonWithTitleEqualTo:@"4f"]; |
+ ASSERT_TRUE(toFolder); |
+ [[toFolder target] performSelector:@selector(openBookmarkFolderFromButton:) |
+ withObject:toFolder]; |
+ BookmarkBarFolderController* folderController = [bar_ folderController]; |
+ EXPECT_TRUE(folderController); |
+ NSWindow* toWindow = [folderController window]; |
+ EXPECT_TRUE(toWindow); |
+ NSRect oldToWindowFrame = [toWindow frame]; |
+ BookmarkButton* toSubfolder = |
+ [folderController buttonWithTitleEqualTo:@"4f2f"]; |
+ ASSERT_TRUE(toSubfolder); |
+ [[toSubfolder target] performSelector:@selector(openBookmarkFolderFromButton:) |
+ withObject:toSubfolder]; |
+ BookmarkBarFolderController* subfolderController = |
+ [folderController folderController]; |
+ EXPECT_TRUE(subfolderController); |
+ NSWindow* toSubwindow = [subfolderController window]; |
+ EXPECT_TRUE(toSubwindow); |
+ NSRect oldToSubwindowFrame = [toSubwindow frame]; |
+ // Drag a bar button onto a bookmark (i.e. not a folder) in a folder |
+ // so it should end up below the target bookmark. |
+ BookmarkButton* draggedButton = [bar_ buttonWithTitleEqualTo:@"5b"]; |
+ ASSERT_TRUE(draggedButton); |
+ BookmarkButton* targetButton = |
+ [subfolderController buttonWithTitleEqualTo:@"4f2f3b"]; |
+ ASSERT_TRUE(targetButton); |
+ [subfolderController dragButton:draggedButton |
+ to:[targetButton center] |
+ copy:NO]; |
+ // The button should have landed just after "2f". |
+ const std::string expected_string("1b 2f:[ 2f1b 2f2f:[ 2f2f1b " |
+ "2f2f2b 2f2f3b ] 2f3b ] 3b 4f:[ 4f1f:[ 4f1f1b 4f1f2b 4f1f3b ] 4f2f:[ " |
+ "4f2f1b 4f2f2b 4f2f3b 5b ] 4f3f:[ 4f3f1b 4f3f2b 4f3f3b ] ] "); |
+ EXPECT_EQ(expected_string, model_test_utils::ModelStringFromNode(root)); |
+ |
+ // Check button spacing. |
+ [folderController validateMenuSpacing]; |
+ [subfolderController validateMenuSpacing]; |
+ |
+ // Check the window layouts. The folder window should not have changed, |
+ // but the subfolder window should have shifted vertically and grown. |
+ NSRect newToWindowFrame = [toWindow frame]; |
+ EXPECT_NSRECT_EQ(oldToWindowFrame, newToWindowFrame); |
+ NSRect newToSubwindowFrame = [toSubwindow frame]; |
+ NSRect expectedToSubwindowFrame = oldToSubwindowFrame; |
+ expectedToSubwindowFrame.origin.y -= bookmarks::kBookmarkFolderButtonHeight; |
+ expectedToSubwindowFrame.size.height += |
+ bookmarks::kBookmarkFolderButtonHeight; |
+ EXPECT_NSRECT_EQ(expectedToSubwindowFrame, newToSubwindowFrame); |
+} |
+ |
+TEST_F(BookmarkBarFolderControllerMenuTest, DragMoveWithinFolder) { |
+ BookmarkModel& model(*profile()->GetBookmarkModel()); |
+ const BookmarkNode* root = model.bookmark_bar_node(); |
+ const std::string model_string("1b 2f:[ 2f1b 2f2f:[ 2f2f1b 2f2f2b " |
+ "2f2f3b ] 2f3b ] 3b 4f:[ 4f1f:[ 4f1f1b 4f1f2b 4f1f3b ] 4f2f:[ 4f2f1b " |
+ "4f2f2b 4f2f3b ] 4f3f:[ 4f3f1b 4f3f2b 4f3f3b ] ] 5b "); |
+ model_test_utils::AddNodesFromModelString(model, root, model_string); |
+ |
+ // Validate initial model. |
+ std::string actualModelString = model_test_utils::ModelStringFromNode(root); |
+ EXPECT_EQ(model_string, actualModelString); |
+ |
+ // Pop up a folder menu. |
+ BookmarkButton* toFolder = [bar_ buttonWithTitleEqualTo:@"4f"]; |
+ ASSERT_TRUE(toFolder); |
+ [[toFolder target] performSelector:@selector(openBookmarkFolderFromButton:) |
+ withObject:toFolder]; |
+ BookmarkBarFolderController* folderController = [bar_ folderController]; |
+ EXPECT_TRUE(folderController); |
+ NSWindow* toWindow = [folderController window]; |
+ EXPECT_TRUE(toWindow); |
+ NSRect oldToWindowFrame = [toWindow frame]; |
+ // Drag a folder button to the top within the same parent. |
+ BookmarkButton* draggedButton = |
+ [folderController buttonWithTitleEqualTo:@"4f2f"]; |
+ ASSERT_TRUE(draggedButton); |
+ BookmarkButton* targetButton = |
+ [folderController buttonWithTitleEqualTo:@"4f1f"]; |
+ ASSERT_TRUE(targetButton); |
+ [folderController dragButton:draggedButton |
+ to:[targetButton top] |
+ copy:NO]; |
+ // The button should have landed above "4f1f". |
+ const std::string expected_string("1b 2f:[ 2f1b 2f2f:[ 2f2f1b " |
+ "2f2f2b 2f2f3b ] 2f3b ] 3b 4f:[ 4f2f:[ 4f2f1b 4f2f2b 4f2f3b ] " |
+ "4f1f:[ 4f1f1b 4f1f2b 4f1f3b ] 4f3f:[ 4f3f1b 4f3f2b 4f3f3b ] ] 5b "); |
+ EXPECT_EQ(expected_string, model_test_utils::ModelStringFromNode(root)); |
+ |
+ // The window should not have gone away. |
+ EXPECT_TRUE([bar_ folderController]); |
+ |
+ // The folder window should not have changed. |
+ NSRect newToWindowFrame = [toWindow frame]; |
+ EXPECT_NSRECT_EQ(oldToWindowFrame, newToWindowFrame); |
+ |
+ // Check button spacing. |
+ [folderController validateMenuSpacing]; |
+} |
+ |
+TEST_F(BookmarkBarFolderControllerMenuTest, DragParentOntoChild) { |
+ BookmarkModel& model(*profile()->GetBookmarkModel()); |
+ const BookmarkNode* root = model.bookmark_bar_node(); |
+ const std::string model_string("1b 2f:[ 2f1b 2f2f:[ 2f2f1b 2f2f2b " |
+ "2f2f3b ] 2f3b ] 3b 4f:[ 4f1f:[ 4f1f1b 4f1f2b 4f1f3b ] 4f2f:[ 4f2f1b " |
+ "4f2f2b 4f2f3b ] 4f3f:[ 4f3f1b 4f3f2b 4f3f3b ] ] 5b "); |
+ model_test_utils::AddNodesFromModelString(model, root, model_string); |
+ |
+ // Validate initial model. |
+ std::string actualModelString = model_test_utils::ModelStringFromNode(root); |
+ EXPECT_EQ(model_string, actualModelString); |
+ |
+ // Pop up a folder menu. |
+ BookmarkButton* toFolder = [bar_ buttonWithTitleEqualTo:@"4f"]; |
+ ASSERT_TRUE(toFolder); |
+ [[toFolder target] performSelector:@selector(openBookmarkFolderFromButton:) |
+ withObject:toFolder]; |
+ BookmarkBarFolderController* folderController = [bar_ folderController]; |
+ EXPECT_TRUE(folderController); |
+ NSWindow* toWindow = [folderController window]; |
+ EXPECT_TRUE(toWindow); |
+ // Drag a folder button to one of its children. |
+ BookmarkButton* draggedButton = [bar_ buttonWithTitleEqualTo:@"4f"]; |
+ ASSERT_TRUE(draggedButton); |
+ BookmarkButton* targetButton = |
+ [folderController buttonWithTitleEqualTo:@"4f3f"]; |
+ ASSERT_TRUE(targetButton); |
+ [folderController dragButton:draggedButton |
+ to:[targetButton top] |
+ copy:NO]; |
+ // The model should not have changed. |
+ EXPECT_EQ(model_string, model_test_utils::ModelStringFromNode(root)); |
+ |
+ // Check button spacing. |
+ [folderController validateMenuSpacing]; |
+} |
+ |
+TEST_F(BookmarkBarFolderControllerMenuTest, DragMoveChildToParent) { |
+ BookmarkModel& model(*profile()->GetBookmarkModel()); |
+ const BookmarkNode* root = model.bookmark_bar_node(); |
+ const std::string model_string("1b 2f:[ 2f1b 2f2f:[ 2f2f1b 2f2f2b " |
+ "2f2f3b ] 2f3b ] 3b 4f:[ 4f1f:[ 4f1f1b 4f1f2b 4f1f3b ] 4f2f:[ 4f2f1b " |
+ "4f2f2b 4f2f3b ] 4f3f:[ 4f3f1b 4f3f2b 4f3f3b ] ] 5b "); |
+ model_test_utils::AddNodesFromModelString(model, root, model_string); |
+ |
+ // Validate initial model. |
+ std::string actualModelString = model_test_utils::ModelStringFromNode(root); |
+ EXPECT_EQ(model_string, actualModelString); |
+ |
+ // Pop up a folder menu and a subfolder menu. |
+ BookmarkButton* toFolder = [bar_ buttonWithTitleEqualTo:@"4f"]; |
+ ASSERT_TRUE(toFolder); |
+ [[toFolder target] performSelector:@selector(openBookmarkFolderFromButton:) |
+ withObject:toFolder]; |
+ BookmarkBarFolderController* folderController = [bar_ folderController]; |
+ EXPECT_TRUE(folderController); |
+ BookmarkButton* toSubfolder = |
+ [folderController buttonWithTitleEqualTo:@"4f2f"]; |
+ ASSERT_TRUE(toSubfolder); |
+ [[toSubfolder target] performSelector:@selector(openBookmarkFolderFromButton:) |
+ withObject:toSubfolder]; |
+ BookmarkBarFolderController* subfolderController = |
+ [folderController folderController]; |
+ EXPECT_TRUE(subfolderController); |
+ |
+ // Drag a subfolder bookmark to the parent folder. |
+ BookmarkButton* draggedButton = |
+ [subfolderController buttonWithTitleEqualTo:@"4f2f3b"]; |
+ ASSERT_TRUE(draggedButton); |
+ BookmarkButton* targetButton = |
+ [folderController buttonWithTitleEqualTo:@"4f2f"]; |
+ ASSERT_TRUE(targetButton); |
+ [folderController dragButton:draggedButton |
+ to:[targetButton top] |
+ copy:NO]; |
+ // The button should have landed above "4f2f". |
+ const std::string expected_string("1b 2f:[ 2f1b 2f2f:[ 2f2f1b 2f2f2b " |
+ "2f2f3b ] 2f3b ] 3b 4f:[ 4f1f:[ 4f1f1b 4f1f2b 4f1f3b ] 4f2f3b 4f2f:[ " |
+ "4f2f1b 4f2f2b ] 4f3f:[ 4f3f1b 4f3f2b 4f3f3b ] ] 5b "); |
+ EXPECT_EQ(expected_string, model_test_utils::ModelStringFromNode(root)); |
+ |
+ // Check button spacing. |
+ [folderController validateMenuSpacing]; |
+ // The window should not have gone away. |
+ EXPECT_TRUE([bar_ folderController]); |
+ // The subfolder should have gone away. |
+ EXPECT_FALSE([folderController folderController]); |
+} |
+ |
+TEST_F(BookmarkBarFolderControllerMenuTest, DragWindowResizing) { |
+ BookmarkModel& model(*profile()->GetBookmarkModel()); |
+ const BookmarkNode* root = model.bookmark_bar_node(); |
+ const std::string |
+ model_string("a b:[ b1 b2 b3 ] reallyReallyLongBookmarkName c "); |
+ model_test_utils::AddNodesFromModelString(model, root, model_string); |
+ |
+ // Validate initial model. |
+ std::string actualModelString = model_test_utils::ModelStringFromNode(root); |
+ EXPECT_EQ(model_string, actualModelString); |
+ |
+ // Pop up a folder menu. |
+ BookmarkButton* toFolder = [bar_ buttonWithTitleEqualTo:@"b"]; |
+ ASSERT_TRUE(toFolder); |
+ [[toFolder target] performSelector:@selector(openBookmarkFolderFromButton:) |
+ withObject:toFolder]; |
+ BookmarkBarFolderController* folderController = [bar_ folderController]; |
+ EXPECT_TRUE(folderController); |
+ NSWindow* toWindow = [folderController window]; |
+ EXPECT_TRUE(toWindow); |
+ CGFloat oldWidth = NSWidth([toWindow frame]); |
+ // Drag the bookmark with a long name to the folder. |
+ BookmarkButton* draggedButton = |
+ [bar_ buttonWithTitleEqualTo:@"reallyReallyLongBookmarkName"]; |
+ ASSERT_TRUE(draggedButton); |
+ BookmarkButton* targetButton = |
+ [folderController buttonWithTitleEqualTo:@"b1"]; |
+ ASSERT_TRUE(targetButton); |
+ [folderController dragButton:draggedButton |
+ to:[targetButton center] |
+ copy:NO]; |
+ // Verify the model change. |
+ const std::string |
+ expected_string("a b:[ b1 reallyReallyLongBookmarkName b2 b3 ] c "); |
+ EXPECT_EQ(expected_string, model_test_utils::ModelStringFromNode(root)); |
+ // Verify the window grew. Just test a reasonable width gain. |
+ CGFloat newWidth = NSWidth([toWindow frame]); |
+ EXPECT_LT(oldWidth + 30.0, newWidth); |
+} |
+ |
+TEST_F(BookmarkBarFolderControllerMenuTest, MoveRemoveAddButtons) { |
+ BookmarkModel& model(*profile()->GetBookmarkModel()); |
+ const BookmarkNode* root = model.bookmark_bar_node(); |
+ const std::string model_string("1b 2f:[ 2f1b 2f2b 2f3b ] 3b 4b "); |
+ model_test_utils::AddNodesFromModelString(model, root, model_string); |
+ |
+ // Validate initial model. |
+ std::string actualModelString = model_test_utils::ModelStringFromNode(root); |
+ EXPECT_EQ(model_string, actualModelString); |
+ |
+ // Pop up a folder menu. |
+ BookmarkButton* toFolder = [bar_ buttonWithTitleEqualTo:@"2f"]; |
+ ASSERT_TRUE(toFolder); |
+ [[toFolder target] performSelector:@selector(openBookmarkFolderFromButton:) |
+ withObject:toFolder]; |
+ BookmarkBarFolderController* folder = [bar_ folderController]; |
+ EXPECT_TRUE(folder); |
+ |
+ // Remember how many buttons are showing. |
+ NSArray* buttons = [folder buttons]; |
+ NSUInteger oldDisplayedButtons = [buttons count]; |
+ |
+ // Move a button around a bit. |
+ [folder moveButtonFromIndex:0 toIndex:2]; |
+ EXPECT_NSEQ(@"2f2b", [[buttons objectAtIndex:0] title]); |
+ EXPECT_NSEQ(@"2f3b", [[buttons objectAtIndex:1] title]); |
+ EXPECT_NSEQ(@"2f1b", [[buttons objectAtIndex:2] title]); |
+ EXPECT_EQ(oldDisplayedButtons, [buttons count]); |
+ [folder moveButtonFromIndex:2 toIndex:0]; |
+ EXPECT_NSEQ(@"2f1b", [[buttons objectAtIndex:0] title]); |
+ EXPECT_NSEQ(@"2f2b", [[buttons objectAtIndex:1] title]); |
+ EXPECT_NSEQ(@"2f3b", [[buttons objectAtIndex:2] title]); |
+ EXPECT_EQ(oldDisplayedButtons, [buttons count]); |
+ |
+ // Add a couple of buttons. |
+ const BookmarkNode* node = root->GetChild(2); // Purloin an existing node. |
+ [folder addButtonForNode:node atIndex:0]; |
+ EXPECT_NSEQ(@"3b", [[buttons objectAtIndex:0] title]); |
+ EXPECT_NSEQ(@"2f1b", [[buttons objectAtIndex:1] title]); |
+ EXPECT_NSEQ(@"2f2b", [[buttons objectAtIndex:2] title]); |
+ EXPECT_NSEQ(@"2f3b", [[buttons objectAtIndex:3] title]); |
+ EXPECT_EQ(oldDisplayedButtons + 1, [buttons count]); |
+ node = root->GetChild(3); |
+ [folder addButtonForNode:node atIndex:-1]; |
+ EXPECT_NSEQ(@"3b", [[buttons objectAtIndex:0] title]); |
+ EXPECT_NSEQ(@"2f1b", [[buttons objectAtIndex:1] title]); |
+ EXPECT_NSEQ(@"2f2b", [[buttons objectAtIndex:2] title]); |
+ EXPECT_NSEQ(@"2f3b", [[buttons objectAtIndex:3] title]); |
+ EXPECT_NSEQ(@"4b", [[buttons objectAtIndex:4] title]); |
+ EXPECT_EQ(oldDisplayedButtons + 2, [buttons count]); |
+ |
+ // Remove a couple of buttons. |
+ [folder removeButton:4 animate:NO]; |
+ [folder removeButton:1 animate:NO]; |
+ EXPECT_NSEQ(@"3b", [[buttons objectAtIndex:0] title]); |
+ EXPECT_NSEQ(@"2f2b", [[buttons objectAtIndex:1] title]); |
+ EXPECT_NSEQ(@"2f3b", [[buttons objectAtIndex:2] title]); |
+ EXPECT_EQ(oldDisplayedButtons, [buttons count]); |
+ |
+ // Check button spacing. |
+ [folder validateMenuSpacing]; |
+} |
+ |
+TEST_F(BookmarkBarFolderControllerMenuTest, ControllerForNode) { |
+ BookmarkModel& model(*profile()->GetBookmarkModel()); |
+ const BookmarkNode* root = model.bookmark_bar_node(); |
+ const std::string model_string("1b 2f:[ 2f1b 2f2b ] 3b "); |
+ model_test_utils::AddNodesFromModelString(model, root, model_string); |
+ |
+ // Validate initial model. |
+ std::string actualModelString = model_test_utils::ModelStringFromNode(root); |
+ EXPECT_EQ(model_string, actualModelString); |
+ |
+ // Find the main bar controller. |
+ const void* expectedController = bar_; |
+ const void* actualController = [bar_ controllerForNode:root]; |
+ EXPECT_EQ(expectedController, actualController); |
+ |
+ // Pop up the folder menu. |
+ BookmarkButton* targetFolder = [bar_ buttonWithTitleEqualTo:@"2f"]; |
+ ASSERT_TRUE(targetFolder); |
+ [[targetFolder target] |
+ performSelector:@selector(openBookmarkFolderFromButton:) |
+ withObject:targetFolder]; |
+ BookmarkBarFolderController* folder = [bar_ folderController]; |
+ EXPECT_TRUE(folder); |
+ |
+ // Find the folder controller using the folder controller. |
+ const BookmarkNode* targetNode = root->GetChild(1); |
+ expectedController = folder; |
+ actualController = [bar_ controllerForNode:targetNode]; |
+ EXPECT_EQ(expectedController, actualController); |
+ |
+ // Find the folder controller from the bar. |
+ actualController = [folder controllerForNode:targetNode]; |
+ EXPECT_EQ(expectedController, actualController); |
+} |
+ |
+TEST_F(BookmarkBarFolderControllerMenuTest, MenuSizingAndScrollArrows) { |
+ BookmarkModel& model(*profile()->GetBookmarkModel()); |
+ const BookmarkNode* root = model.bookmark_bar_node(); |
+ const std::string model_string("1b 2b 3b "); |
+ model_test_utils::AddNodesFromModelString(model, root, model_string); |
+ |
+ // Validate initial model. |
+ std::string actualModelString = model_test_utils::ModelStringFromNode(root); |
+ EXPECT_EQ(model_string, actualModelString); |
+ |
+ const BookmarkNode* parent = model.bookmark_bar_node(); |
+ const BookmarkNode* folder = model.AddFolder(parent, |
+ parent->child_count(), |
+ ASCIIToUTF16("BIG")); |
+ |
+ // Pop open the new folder window and verify it has one (empty) item. |
+ BookmarkButton* button = [bar_ buttonWithTitleEqualTo:@"BIG"]; |
+ [[button target] performSelector:@selector(openBookmarkFolderFromButton:) |
+ withObject:button]; |
+ BookmarkBarFolderController* folderController = [bar_ folderController]; |
+ EXPECT_TRUE(folderController); |
+ NSWindow* folderWindow = [folderController window]; |
+ EXPECT_TRUE(folderWindow); |
+ CGFloat expectedHeight = (CGFloat)bookmarks::kBookmarkFolderButtonHeight + |
+ (2*bookmarks::kBookmarkVerticalPadding); |
+ NSRect windowFrame = [folderWindow frame]; |
+ CGFloat windowHeight = NSHeight(windowFrame); |
+ EXPECT_CGFLOAT_EQ(expectedHeight, windowHeight); |
+ EXPECT_FALSE([folderController canScrollUp]); |
+ EXPECT_FALSE([folderController canScrollDown]); |
+ |
+ // Now add a real bookmark and reopen. |
+ model.AddURL(folder, folder->child_count(), ASCIIToUTF16("a"), |
+ GURL("http://a.com/")); |
+ folderController = [bar_ folderController]; |
+ EXPECT_TRUE(folderController); |
+ NSView* folderView = [folderController folderView]; |
+ EXPECT_TRUE(folderView); |
+ NSRect menuFrame = [folderView frame]; |
+ NSView* visibleView = [folderController visibleView]; |
+ NSRect visibleFrame = [visibleView frame]; |
+ NSScrollView* scrollView = [folderController scrollView]; |
+ NSRect scrollFrame = [scrollView frame]; |
+ |
+ // Determine the margins between the scroll frame and the visible frame. |
+ CGFloat widthDelta = NSWidth(visibleFrame) - NSWidth(scrollFrame); |
+ |
+ CGFloat menuHeight = NSHeight(menuFrame); |
+ EXPECT_CGFLOAT_EQ(expectedHeight, menuHeight); |
+ CGFloat scrollerWidth = NSWidth(scrollFrame); |
+ button = [folderController buttonWithTitleEqualTo:@"a"]; |
+ CGFloat buttonWidth = NSWidth([button frame]); |
+ EXPECT_CGFLOAT_EQ(scrollerWidth, buttonWidth); |
+ CGFloat visibleWidth = NSWidth(visibleFrame); |
+ EXPECT_CGFLOAT_EQ(visibleWidth - widthDelta, buttonWidth); |
+ EXPECT_LT(scrollerWidth, NSWidth([folderView frame])); |
+ |
+ // Add a wider bookmark and make sure the button widths match. |
+ int reallyWideButtonNumber = folder->child_count(); |
+ model.AddURL(folder, reallyWideButtonNumber, |
+ ASCIIToUTF16("A really, really, really, really, really, " |
+ "really long name"), |
+ GURL("http://www.google.com/a")); |
+ BookmarkButton* bigButton = |
+ [folderController buttonWithTitleEqualTo: |
+ @"A really, really, really, really, really, really long name"]; |
+ EXPECT_TRUE(bigButton); |
+ CGFloat buttonWidthB = NSWidth([bigButton frame]); |
+ EXPECT_LT(buttonWidth, buttonWidthB); |
+ // Add a bunch of bookmarks until the window becomes scrollable, then check |
+ // for a scroll up arrow. |
+ NSUInteger tripWire = 0; // Prevent a runaway. |
+ while (![folderController canScrollUp] && ++tripWire < 1000) { |
+ model.AddURL(folder, folder->child_count(), ASCIIToUTF16("B"), |
+ GURL("http://b.com/")); |
+ } |
+ EXPECT_TRUE([folderController canScrollUp]); |
+ |
+ // Remove one bookmark and make sure the scroll down arrow has been removed. |
+ // We'll remove the really long node so we can see if the buttons get resized. |
+ scrollerWidth = NSWidth([folderView frame]); |
+ buttonWidth = NSWidth([button frame]); |
+ model.Remove(folder, reallyWideButtonNumber); |
+ EXPECT_FALSE([folderController canScrollUp]); |
+ EXPECT_FALSE([folderController canScrollDown]); |
+ |
+ // Check the size. It should have reduced. |
+ EXPECT_GT(scrollerWidth, NSWidth([folderView frame])); |
+ EXPECT_GT(buttonWidth, NSWidth([button frame])); |
+ |
+ // Check button spacing. |
+ [folderController validateMenuSpacing]; |
+} |
+ |
+// See http://crbug.com/46101 |
+TEST_F(BookmarkBarFolderControllerMenuTest, HoverThenDeleteBookmark) { |
+ BookmarkModel& model(*profile()->GetBookmarkModel()); |
+ const BookmarkNode* root = model.bookmark_bar_node(); |
+ const BookmarkNode* folder = model.AddFolder(root, |
+ root->child_count(), |
+ ASCIIToUTF16("BIG")); |
+ for (int i = 0; i < kLotsOfNodesCount; i++) |
+ model.AddURL(folder, folder->child_count(), ASCIIToUTF16("kid"), |
+ GURL("http://kid.com/smile")); |
+ |
+ // Pop open the new folder window and hover one of its kids. |
+ BookmarkButton* button = [bar_ buttonWithTitleEqualTo:@"BIG"]; |
+ [[button target] performSelector:@selector(openBookmarkFolderFromButton:) |
+ withObject:button]; |
+ BookmarkBarFolderController* bbfc = [bar_ folderController]; |
+ NSArray* buttons = [bbfc buttons]; |
+ |
+ // Hover over a button and verify that it is now known. |
+ button = [buttons objectAtIndex:3]; |
+ BookmarkButton* buttonThatMouseIsIn = [bbfc buttonThatMouseIsIn]; |
+ EXPECT_FALSE(buttonThatMouseIsIn); |
+ [bbfc mouseEnteredButton:button event:nil]; |
+ buttonThatMouseIsIn = [bbfc buttonThatMouseIsIn]; |
+ EXPECT_EQ(button, buttonThatMouseIsIn); |
+ |
+ // Delete the bookmark and verify that it is now not known. |
+ model.Remove(folder, 3); |
+ buttonThatMouseIsIn = [bbfc buttonThatMouseIsIn]; |
+ EXPECT_FALSE(buttonThatMouseIsIn); |
+} |
+ |
+// Just like a BookmarkBarFolderController but intercedes when providing |
+// pasteboard drag data. |
+@interface BookmarkBarFolderControllerDragData : BookmarkBarFolderController { |
+ const BookmarkNode* dragDataNode_; // Weak |
+} |
+- (void)setDragDataNode:(const BookmarkNode*)node; |
+@end |
+ |
+@implementation BookmarkBarFolderControllerDragData |
+ |
+- (id)initWithParentButton:(BookmarkButton*)button |
+ parentController:(BookmarkBarFolderController*)parentController |
+ barController:(BookmarkBarController*)barController { |
+ if ((self = [super initWithParentButton:button |
+ parentController:parentController |
+ barController:barController])) { |
+ dragDataNode_ = NULL; |
+ } |
+ return self; |
+} |
+ |
+- (void)setDragDataNode:(const BookmarkNode*)node { |
+ dragDataNode_ = node; |
+} |
+ |
+- (std::vector<const BookmarkNode*>)retrieveBookmarkNodeData { |
+ std::vector<const BookmarkNode*> dragDataNodes; |
+ if(dragDataNode_) { |
+ dragDataNodes.push_back(dragDataNode_); |
+ } |
+ return dragDataNodes; |
+} |
+ |
+@end |
+ |
+TEST_F(BookmarkBarFolderControllerMenuTest, DragBookmarkData) { |
+ BookmarkModel& model(*profile()->GetBookmarkModel()); |
+ const BookmarkNode* root = model.bookmark_bar_node(); |
+ const std::string model_string("1b 2f:[ 2f1b 2f2f:[ 2f2f1b 2f2f2b 2f2f3b ] " |
+ "2f3b ] 3b 4b "); |
+ model_test_utils::AddNodesFromModelString(model, root, model_string); |
+ const BookmarkNode* other = model.other_node(); |
+ const std::string other_string("O1b O2b O3f:[ O3f1b O3f2f ] " |
+ "O4f:[ O4f1b O4f2f ] 05b "); |
+ model_test_utils::AddNodesFromModelString(model, other, other_string); |
+ |
+ // Validate initial model. |
+ std::string actual = model_test_utils::ModelStringFromNode(root); |
+ EXPECT_EQ(model_string, actual); |
+ actual = model_test_utils::ModelStringFromNode(other); |
+ EXPECT_EQ(other_string, actual); |
+ |
+ // Pop open a folder. |
+ BookmarkButton* button = [bar_ buttonWithTitleEqualTo:@"2f"]; |
+ scoped_nsobject<BookmarkBarFolderControllerDragData> folderController; |
+ folderController.reset([[BookmarkBarFolderControllerDragData alloc] |
+ initWithParentButton:button |
+ parentController:nil |
+ barController:bar_]); |
+ BookmarkButton* targetButton = |
+ [folderController buttonWithTitleEqualTo:@"2f1b"]; |
+ ASSERT_TRUE(targetButton); |
+ |
+ // Gen up some dragging data. |
+ const BookmarkNode* newNode = other->GetChild(2); |
+ [folderController setDragDataNode:newNode]; |
+ scoped_nsobject<FakedDragInfo> dragInfo([[FakedDragInfo alloc] init]); |
+ [dragInfo setDropLocation:[targetButton top]]; |
+ [folderController dragBookmarkData:(id<NSDraggingInfo>)dragInfo.get()]; |
+ |
+ // Verify the model. |
+ const std::string expected("1b 2f:[ O3f:[ O3f1b O3f2f ] 2f1b 2f2f:[ 2f2f1b " |
+ "2f2f2b 2f2f3b ] 2f3b ] 3b 4b "); |
+ actual = model_test_utils::ModelStringFromNode(root); |
+ EXPECT_EQ(expected, actual); |
+ |
+ // Now drag over a folder button. |
+ targetButton = [folderController buttonWithTitleEqualTo:@"2f2f"]; |
+ ASSERT_TRUE(targetButton); |
+ newNode = other->GetChild(2); // Should be O4f. |
+ EXPECT_EQ(newNode->GetTitle(), ASCIIToUTF16("O4f")); |
+ [folderController setDragDataNode:newNode]; |
+ [dragInfo setDropLocation:[targetButton center]]; |
+ [folderController dragBookmarkData:(id<NSDraggingInfo>)dragInfo.get()]; |
+ |
+ // Verify the model. |
+ const std::string expectedA("1b 2f:[ O3f:[ O3f1b O3f2f ] 2f1b 2f2f:[ " |
+ "2f2f1b 2f2f2b 2f2f3b O4f:[ O4f1b O4f2f ] ] " |
+ "2f3b ] 3b 4b "); |
+ actual = model_test_utils::ModelStringFromNode(root); |
+ EXPECT_EQ(expectedA, actual); |
+ |
+ // Check button spacing. |
+ [folderController validateMenuSpacing]; |
+} |
+ |
+TEST_F(BookmarkBarFolderControllerMenuTest, DragBookmarkDataToTrash) { |
+ BookmarkModel& model(*profile()->GetBookmarkModel()); |
+ const BookmarkNode* root = model.bookmark_bar_node(); |
+ const std::string model_string("1b 2f:[ 2f1b 2f2f:[ 2f2f1b 2f2f2b 2f2f3b ] " |
+ "2f3b ] 3b 4b "); |
+ model_test_utils::AddNodesFromModelString(model, root, model_string); |
+ |
+ // Validate initial model. |
+ std::string actual = model_test_utils::ModelStringFromNode(root); |
+ EXPECT_EQ(model_string, actual); |
+ |
+ const BookmarkNode* folderNode = root->GetChild(1); |
+ int oldFolderChildCount = folderNode->child_count(); |
+ |
+ // Pop open a folder. |
+ BookmarkButton* button = [bar_ buttonWithTitleEqualTo:@"2f"]; |
+ scoped_nsobject<BookmarkBarFolderControllerDragData> folderController; |
+ folderController.reset([[BookmarkBarFolderControllerDragData alloc] |
+ initWithParentButton:button |
+ parentController:nil |
+ barController:bar_]); |
+ |
+ // Drag a button to the trash. |
+ BookmarkButton* buttonToDelete = |
+ [folderController buttonWithTitleEqualTo:@"2f1b"]; |
+ ASSERT_TRUE(buttonToDelete); |
+ EXPECT_TRUE([folderController canDragBookmarkButtonToTrash:buttonToDelete]); |
+ [folderController didDragBookmarkToTrash:buttonToDelete]; |
+ |
+ // There should be one less button in the folder. |
+ int newFolderChildCount = folderNode->child_count(); |
+ EXPECT_EQ(oldFolderChildCount - 1, newFolderChildCount); |
+ // Verify the model. |
+ const std::string expected("1b 2f:[ 2f2f:[ 2f2f1b 2f2f2b 2f2f3b ] " |
+ "2f3b ] 3b 4b "); |
+ actual = model_test_utils::ModelStringFromNode(root); |
+ EXPECT_EQ(expected, actual); |
+ |
+ // Check button spacing. |
+ [folderController validateMenuSpacing]; |
+} |
+ |
+TEST_F(BookmarkBarFolderControllerMenuTest, AddURLs) { |
+ BookmarkModel& model(*profile()->GetBookmarkModel()); |
+ const BookmarkNode* root = model.bookmark_bar_node(); |
+ const std::string model_string("1b 2f:[ 2f1b 2f2f:[ 2f2f1b 2f2f2b 2f2f3b ] " |
+ "2f3b ] 3b 4b "); |
+ model_test_utils::AddNodesFromModelString(model, root, model_string); |
+ |
+ // Validate initial model. |
+ std::string actual = model_test_utils::ModelStringFromNode(root); |
+ EXPECT_EQ(model_string, actual); |
+ |
+ // Pop open a folder. |
+ BookmarkButton* button = [bar_ buttonWithTitleEqualTo:@"2f"]; |
+ [[button target] performSelector:@selector(openBookmarkFolderFromButton:) |
+ withObject:button]; |
+ BookmarkBarFolderController* folderController = [bar_ folderController]; |
+ EXPECT_TRUE(folderController); |
+ NSArray* buttons = [folderController buttons]; |
+ EXPECT_TRUE(buttons); |
+ |
+ // Remember how many buttons are showing. |
+ int oldDisplayedButtons = [buttons count]; |
+ |
+ BookmarkButton* targetButton = |
+ [folderController buttonWithTitleEqualTo:@"2f1b"]; |
+ ASSERT_TRUE(targetButton); |
+ |
+ NSArray* urls = [NSArray arrayWithObjects: @"http://www.a.com/", |
+ @"http://www.b.com/", nil]; |
+ NSArray* titles = [NSArray arrayWithObjects: @"SiteA", @"SiteB", nil]; |
+ [folderController addURLs:urls withTitles:titles at:[targetButton top]]; |
+ |
+ // There should two more buttons in the folder. |
+ int newDisplayedButtons = [buttons count]; |
+ EXPECT_EQ(oldDisplayedButtons + 2, newDisplayedButtons); |
+ // Verify the model. |
+ const std::string expected("1b 2f:[ SiteA SiteB 2f1b 2f2f:[ 2f2f1b 2f2f2b " |
+ "2f2f3b ] 2f3b ] 3b 4b "); |
+ actual = model_test_utils::ModelStringFromNode(root); |
+ EXPECT_EQ(expected, actual); |
+ |
+ // Check button spacing. |
+ [folderController validateMenuSpacing]; |
+} |
+ |
+TEST_F(BookmarkBarFolderControllerMenuTest, DropPositionIndicator) { |
+ BookmarkModel& model(*profile()->GetBookmarkModel()); |
+ const BookmarkNode* root = model.bookmark_bar_node(); |
+ const std::string model_string("1b 2f:[ 2f1b 2f2f:[ 2f2f1b 2f2f2b 2f2f3b ] " |
+ "2f3b ] 3b 4b "); |
+ model_test_utils::AddNodesFromModelString(model, root, model_string); |
+ |
+ // Validate initial model. |
+ std::string actual = model_test_utils::ModelStringFromNode(root); |
+ EXPECT_EQ(model_string, actual); |
+ |
+ // Pop open the folder. |
+ BookmarkButton* button = [bar_ buttonWithTitleEqualTo:@"2f"]; |
+ [[button target] performSelector:@selector(openBookmarkFolderFromButton:) |
+ withObject:button]; |
+ BookmarkBarFolderController* folder = [bar_ folderController]; |
+ EXPECT_TRUE(folder); |
+ |
+ // Test a series of points starting at the top of the folder. |
+ const CGFloat yOffset = 0.5 * bookmarks::kBookmarkVerticalPadding; |
+ BookmarkButton* targetButton = [folder buttonWithTitleEqualTo:@"2f1b"]; |
+ ASSERT_TRUE(targetButton); |
+ NSPoint targetPoint = [targetButton top]; |
+ CGFloat pos = [folder indicatorPosForDragToPoint:targetPoint]; |
+ EXPECT_CGFLOAT_EQ(targetPoint.y + yOffset, pos); |
+ pos = [folder indicatorPosForDragToPoint:[targetButton bottom]]; |
+ targetButton = [folder buttonWithTitleEqualTo:@"2f2f"]; |
+ EXPECT_CGFLOAT_EQ([targetButton top].y + yOffset, pos); |
+ pos = [folder indicatorPosForDragToPoint:NSMakePoint(10,0)]; |
+ targetButton = [folder buttonWithTitleEqualTo:@"2f3b"]; |
+ EXPECT_CGFLOAT_EQ([targetButton bottom].y - yOffset, pos); |
+} |
+ |
+@interface BookmarkBarControllerNoDelete : BookmarkBarController |
+- (IBAction)deleteBookmark:(id)sender; |
+@end |
+ |
+@implementation BookmarkBarControllerNoDelete |
+- (IBAction)deleteBookmark:(id)sender { |
+ // NOP |
+} |
+@end |
+ |
+class BookmarkBarFolderControllerClosingTest : public |
+ BookmarkBarFolderControllerMenuTest { |
+ public: |
+ virtual void SetUp() { |
+ BookmarkBarFolderControllerMenuTest::SetUp(); |
+ ASSERT_TRUE(browser()); |
+ |
+ bar_.reset([[BookmarkBarControllerNoDelete alloc] |
+ initWithBrowser:browser() |
+ initialWidth:NSWidth([parent_view_ frame]) |
+ delegate:nil |
+ resizeDelegate:resizeDelegate_.get()]); |
+ InstallAndToggleBar(bar_.get()); |
+ } |
+}; |
+ |
+TEST_F(BookmarkBarFolderControllerClosingTest, DeleteClosesFolder) { |
+ BookmarkModel& model(*profile()->GetBookmarkModel()); |
+ const BookmarkNode* root = model.bookmark_bar_node(); |
+ const std::string model_string("1b 2f:[ 2f1b 2f2f:[ 2f2f1b 2f2f2b ] " |
+ "2f3b ] 3b "); |
+ model_test_utils::AddNodesFromModelString(model, root, model_string); |
+ |
+ // Validate initial model. |
+ std::string actualModelString = model_test_utils::ModelStringFromNode(root); |
+ EXPECT_EQ(model_string, actualModelString); |
+ |
+ // Open the folder menu and submenu. |
+ BookmarkButton* target = [bar_ buttonWithTitleEqualTo:@"2f"]; |
+ ASSERT_TRUE(target); |
+ [[target target] performSelector:@selector(openBookmarkFolderFromButton:) |
+ withObject:target]; |
+ BookmarkBarFolderController* folder = [bar_ folderController]; |
+ EXPECT_TRUE(folder); |
+ BookmarkButton* subTarget = [folder buttonWithTitleEqualTo:@"2f2f"]; |
+ ASSERT_TRUE(subTarget); |
+ [[subTarget target] performSelector:@selector(openBookmarkFolderFromButton:) |
+ withObject:subTarget]; |
+ BookmarkBarFolderController* subFolder = [folder folderController]; |
+ EXPECT_TRUE(subFolder); |
+ |
+ // Delete the folder node and verify the window closed down by looking |
+ // for its controller again. |
+ [folder deleteBookmark:folder]; |
+ EXPECT_FALSE([folder folderController]); |
+} |
+ |
+// TODO(jrg): draggingEntered: and draggingExited: trigger timers so |
+// they are hard to test. Factor out "fire timers" into routines |
+// which can be overridden to fire immediately to make behavior |
+// confirmable. |
+// There is a similar problem with mouseEnteredButton: and |
+// mouseExitedButton:. |