Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(427)

Unified Diff: chrome/browser/ui/cocoa/bookmarks/bookmark_bar_folder_controller_unittest.mm

Issue 8141003: [Mac] Restore the old bookmark menus now that the experiment is over. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 9 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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:.

Powered by Google App Engine
This is Rietveld 408576698